home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / c / nkcc / nkcc.s < prev    next >
Encoding:
Text File  |  1994-09-22  |  146.6 KB  |  3,657 lines

  1. ********************************************************************************
  2. *
  3. *  Project name : NORMALIZED KEY CODE CONVERTER (NKCC)
  4. *  Module name  : Main module
  5. *  Symbol prefix: nkc
  6. *
  7. *  Author       : Harald Siegmund (HS)
  8. *  Co-Authors   : -
  9. *  Write access : HS
  10. *
  11. *  Notes        : The symbol NKCGEM will have to be defined on the assembler's
  12. *                 command line when translating the source of NKCC. Set its
  13. *                 value to 1 if you like to create the complete version. A value
  14. *                 of 0 will supress inclusion of the GEM part, making NKCC a few
  15. *                 KBytes smaller. Some functions and the GEM parameter arrays
  16. *                 are not available then.
  17. *
  18. *                 Translate this source with the MadMac assembler:
  19. *                 mac -dNKCGEM=1 -onkcc.o nkcc.s
  20. *                 mac -dNKCGEM=0 -onkcc_tos.o nkcc.s
  21. *
  22. *-------------------------------------------------------------------------------
  23. *  NKCC was developed with Atari's MadMac assembler. It should be possible to
  24. *  adapt the source to different assemblers with minor effort. Here's an
  25. *  overview of all MadMac-specific assembly directives used in this source file:
  26. *
  27. *  .globl         declares a symbol to be imported from another module
  28. *                  respectively exported from the current source (depending if
  29. *                  the symbol is defined in the source or not)
  30. *  .if <expr>     conditional assembly; <expr> is tested to be non-zero (true)
  31. *                 or zero (false)
  32. *  .else
  33. *  .endif
  34. *  =              equate
  35. *  .abs           absolute section; is usually used to defined structure
  36. *                  offsets. Labels in the absolute section get a constant
  37. *                  value and usually have a .ds directive in their opcode
  38. *                  field incrementing the value for the next label
  39. *  .macro         introcudes a macro definition
  40. *  .endm          ends a macro definition
  41. *
  42. *  Macros:
  43. *   .macro name [argument,argument,...]
  44. *   Arguments accesses inside the macro must have a backslash character
  45. *    (e.g. move   \argument1,d0)
  46. *   The expression  \?{argument}  tests if an argument is defined or not.
  47. *
  48. *  Symbols:
  49. *   MadMac supports local symbols with a limited scope. Their name starts with
  50. *   a period (.) and their scope ends at the next global symbol (in both
  51. *   directions).
  52. *
  53. *-------------------------------------------------------------------------------
  54. *  Things to do :
  55. *
  56. *  -  NKCC will support additional (and more complex) deadkeys some time, such
  57. *     like Arabian ones. A communication interface between NKCC and a text
  58. *     editor will be built in for that purpose (Arabian languages' deadkeys can
  59. *     affect existing text!).
  60. *
  61. *-------------------------------------------------------------------------------
  62. *  History:
  63. *
  64. *  1989:
  65. *     May 14: creation of file (NKCC 1.00)
  66. *     Jun 07/15-16/19/21/Jul 11: improvements, changes, debugging
  67. *  1990:
  68. *     Jan 13: global functions now available in two versions:
  69. *             parameters passed via registers (e.g. for Turbo C)
  70. *             parameters passed via stack (underscore before label name)
  71. *
  72. *     May 23-24/26-28: creation of NKCC 2.00 (almost every function rewritten)
  73. *     Jun 16/27: assembler-entry added by Gerd Knops
  74. *     Jun 30/Jul 02: return shift key flags in nkc_multi()/amulti() as NKF?_...
  75. *     Jul 09: nkc_kstate()
  76. *     Aug 03: nkc_cmp()
  77. *     Aug 18: fatal bug in nkc_kstate() fixed
  78. *     Sep 15: nkc_timer()
  79. *     Sep 15-17/30: own button event handler
  80. *     Oct 03: debugging
  81. *             nkc_vlink()/vunlink()
  82. *             documentation syntax changed (LRef/XRef removed; Reg: changed)
  83. *     Oct 05: debugging mouse button handler (problems with menu bar)
  84. *     Oct 07: Control/Alternate + character always returns capital characters
  85. *             changing key code comparism rules in nkc_cmp()
  86. *     Oct 22: debugging nkc_cmp() (did sometimes recognize unique key codes)
  87. *             debugging ASCII code input in nkc_amulti()
  88. *     Dec 11/15/17: MU_XTIMER
  89. *  1991:
  90. *     Jan 11: don't call AES with set MU_XTIMER flag
  91. *     Mar 31: ensure that evnt_multi() parameters are restored when being
  92. *             corrupted by a bug in AES!!
  93. *     Apr 01: debugging
  94. *     Apr 13: nkc_conv() renamed to nkc_tconv()
  95. *     Apr 13-14: nkc_gconv()
  96. *     May 10: debugging (nk_beend())
  97. *     May 29: debugging (double shift key compare)
  98. *             export nkc_toupper and nkc_tolower
  99. *     Jul 05: completing history
  100. *     Jul 31: version number before XBRA header
  101. *     Aug 06: " is now a deadkey!
  102. *     Aug 07: more deadkeys...
  103. *     Aug 22: deadkeys can now be enabled/disabled separately
  104. *             nkc_set() changed
  105. *             nkc_init() returns version #
  106. *             bug fixed: nkc_cmp() corrupted high words of D3 and D4
  107. *     Sep 07/14: nkc_cmp() improved; NKF?_RESVD now in use
  108. *     Nov 05: adjustments to ASCII input feature of TOS 3.06
  109. *     Nov 16: bug fixed in nkc_cmp() mechanism
  110. *             Control key emulation
  111. *     Dec 29: small corrections and extensions of the documentation
  112. *             source documentation syntax now in extra file
  113. *  1992:
  114. *     Jan 03: changing documentation of nkc_init()
  115. *             revising info lines in function headers
  116. *     Jan 12: adjusting nkc_init() to its new documentation!
  117. *             appending .b respectively .l to all instructions with a default
  118. *              operand size which is not .w
  119. *             changing macro XBRA_HD
  120. *     Feb 11: adjusting button event handler to MINT
  121. *     Feb 28: NKCOWNPB switch
  122. *  1993:
  123. *     Dec 11: merging the two existing NKCC versions to one source:
  124. *             - version number set to $0290
  125. *             - NKCNOGEM/NKCOWNPB keys replaced by NKCGEM key
  126. *             - NKCC uses its own AES/VDI parameter arrays now
  127. *             - nkc_init() gets one more parameter: ^AES global array
  128. *             - nkc_toupper and nkc_tolower are functions now
  129. *             - dynamic double click time
  130. *             - MU_MESAG occured -> don't create self-made button events
  131. *     Dec 12: GEM keyboard events: try to get original shift flags from the
  132. *              Iorec buffer
  133. *             new functions: nkc_n2tos() and nkc_n2gem()
  134. *     Dec 13: debugging: ! operator changed to ~ in nk_bestart
  135. *             implementing nkc_n2tos()
  136. *             size of GEM parameter arrays changed to 32 (larger than required
  137. *              but better too big than too small!)
  138. *     Dec 16: debugging nkc_n2tos()
  139. *     Dec 19: improving nkc_gconv() (scan code translation table)
  140. *             debugging nkc_n2tos()
  141. *             cosmetic changes
  142. *     Dec 23: debugging nkc_vunlink(): return status was garbage!
  143. *  1994:
  144. *     May 19: release 2.91:
  145. *             don't restore conterm (it may be changed by another process in
  146. *              the meantime)
  147. *             new deadkeys (/2 /4)
  148. *             adding overview of used MadMac directives in the note section of
  149. *              the file header
  150. *
  151. ********************************************************************************
  152. *KEY _NAME="NKCC"
  153. *END
  154.  
  155. VERSION        =     $0291                   ; NKCC's version #
  156.  
  157.  
  158. *START
  159. ****************************************************************************
  160. *                         ASSEMBLER CONTROL SECTION                        *
  161. ****************************************************************************
  162.  
  163. *KEY &NKCGEM
  164. *     define this symbol on the assembler's command line
  165. *     =0    create TOS-version of NKCC (without GEM part)
  166. *     =1    create GEM-version of NKCC
  167.  
  168.                .include "nkcc.sh"            ; NKCC definitions
  169. *END
  170. *KEY _END
  171.  
  172.  
  173.  
  174. *START
  175. ****************************************************************************
  176. *                                  EXPORT                                  *
  177. ****************************************************************************
  178.  
  179.                                              ; functions
  180.                .globl   nkc_init             ; init NKCC
  181.                .globl   nkc_exit             ; exit NKCC
  182.                .globl   nkc_set              ; set special key flags
  183.                .globl   nkc_conin            ; NKCC key input via GEMDOS
  184.                .globl   nkc_cstat            ; console input status via GEMDOS
  185.                .globl   nkc_tconv            ; TOS key code converter
  186.                .globl   nkc_gconv            ; GEM key code converter
  187.                .globl   nkc_n2tos            ; NKC to TOS key code converter
  188.                .globl   nkc_n2gem            ; NKC to GEM key code converter
  189.                .globl   nkc_kstate           ; return shift key state
  190.                .globl   nkc_timer            ; return 200 Hz system clock
  191.                .globl   nkc_cmp              ; compare two key codes
  192.                .globl   nkc_vlink            ; link function to XBRA vector list
  193.                .globl   nkc_vunlink          ; unlink function from XBRA list
  194.                .globl   nkc_toupper          ; convert character to upper case
  195.                .globl   nkc_tolower          ; convert character to lower case
  196.  
  197.                .if      NKCGEM=1
  198.  
  199.                 .globl  nkc_multi            ; NKCC multi event handler
  200.                 .globl  nkc_amulti           ; multi event, assembler binding
  201.                 .globl  nkc_contrl           ; GEM parameter arrays
  202.                 .globl  nkc_intin
  203.                 .globl  nkc_intout
  204.                 .globl  nkc_adrin
  205.                 .globl  nkc_adrout
  206.                 .globl  nkc_ptsin
  207.                 .globl  nkc_ptsout
  208.  
  209.                .endif   ; .if NKCGEM=1
  210. *END
  211.  
  212.  
  213.  
  214. ****************************************************************************
  215. *                                  EQUATES                                 *
  216. ****************************************************************************
  217.  
  218.                                              ; AES event mask bits
  219. MU_KEYBD       =        $0001                ; keyboard
  220. MU_BUTTON      =        $0002                ; mouse button clicks
  221. MU_M1          =        $0004                ; mouse movement #1
  222. MU_M2          =        $0008                ; mouse movement #2
  223. MU_MESAG       =        $0010                ; message
  224. MU_TIMER       =        $0020                ; timer
  225.  
  226. conterm        =        $484                 ; .B: system key flags
  227. _hz_200        =        $4ba                 ; .L: 200 Hz system clock
  228. _sysbase       =        $4f2                 ; .L: ^OS header
  229.  
  230. TIME_ADD       =        20                   ; wait time to add on each click
  231.                                              ;  in 1/200 s (-> 100 ms)
  232.  
  233.  
  234. ****************************************************************************
  235. *                             ABSOLUTE SECTION                             *
  236. ****************************************************************************
  237.  
  238.                .abs                          ; button event info block
  239.  
  240. BI_BSTATE:     .ds.w    1                    ; requested button state
  241. BI_BMASK:      .ds.w    1                    ; requested button mask
  242. BI_REVCOND:    .ds.w    1                    ; event condition reverse flag
  243. BI_MAXCLICKS:  .ds.w    1                    ; max # of clicks to wait for
  244. BI_DCLTIME:    .ds.w    1                    ; AES double click time
  245. BI_BMODE:      .ds.w    1                    ; button handler mode (see
  246.                                              ;  function nk_butvec)
  247. BI_SBSTATE:    .ds.w    1                    ; button state at start of event
  248. BI_PRVBSTATE:  .ds.w    1                    ; previous button state
  249. BI_NCLICKS:    .ds.w    1                    ; # of mouse clicks
  250. BI_DCBUT:      .ds.w    1                    ; double click button mask
  251. BI_DCSTATE:    .ds.w    1                    ; double click button state
  252. BI_BENDTIME:   .ds.l    1                    ; button event timer end value
  253. BI_BEVALID:    .ds.b    1                    ; flag: button event valid
  254. BI_CVALID:     .ds.b    1                    ; flag: button condition valid
  255. BI_LOCK:       .ds.b    1                    ; flag: button event locked
  256.                .even
  257. BI:                                          ; size
  258.  
  259.  
  260.                .abs                          ; IOREC structure
  261.  
  262. IBUF:          .ds.l    1                    ; ^base of I/O buffer
  263. IBUFSIZ:       .ds.w    1                    ; size of buffer in bytes
  264. IBUFHD:        .ds.w    1                    ; head-pointer (offset to last
  265.                                              ;  used read position
  266. IBUFTL:        .ds.w    1                    ; tail-pointer (offset to last
  267.                                              ;  used write position
  268. IBUFLO:        .ds.w    1                    ; low water mark
  269. IBUFHI:        .ds.w    1                    ; high water mark
  270. IOREC:                                       ; size
  271.  
  272.  
  273.  
  274. ****************************************************************************
  275. *                                  MACROS                                  *
  276. ****************************************************************************
  277.  
  278. ****************************************************************************
  279. *
  280. * LWDIVU: divide long value <da> by word value <db>, use <dt> for temp storage
  281. *
  282. * - the result will be stored as LONGword in <da>
  283. * - <db> stays unchanged
  284. * - <da> and <dt> must be data registers
  285. *
  286. ****************************************************************************
  287.  
  288.                .macro   LWDIVU .db,.da,.dt
  289.  
  290.                move.l   \.da,\.dt            ; copy long-value
  291.                clr      \.dt                 ; clear its low word
  292.                swap     \.dt                 ; dt.w = high word of long-value
  293.                divu     \.db,\.dt            ; high word / word-value
  294.                swap     \.da                 ; long-value, low and high swapped
  295.                move     \.dt,\.da            ; da.w = result of high/word-value
  296.                swap     \.da                 ; da.w = low word of long-value
  297.                move     \.da,\.dt            ; remainder and low-word
  298.                divu     \.db,\.dt            ; divide by word-value
  299.                move     \.dt,\.da            ; so we get low word of result
  300.  
  301.                .endm
  302.  
  303.  
  304.  
  305. ****************************************************************************
  306. *
  307. * XBRA_HD: XBRA header for NKCC functions
  308. *
  309. * The following structure is stored at the current memory location:
  310. *
  311. * VERSION.L       NKCC's version # (actually not a part of a standard XBRA
  312. *                 header; may be checked in future versions)
  313. * "XBRA".L        magic longword
  314. * "NKCC".L        NKCC's XBRA-ID
  315. * oldvec.L        initial value of buffer for old vector content (passed as
  316. *                 macro parameter); if not defined, the default 0 is used
  317. *
  318. ****************************************************************************
  319.  
  320.                .macro   XBRA_HD .oldvec
  321.  
  322.                .dc.l    VERSION              ; version number
  323.                .dc.b    "XBRA"               ; XBRA header
  324.                .dc.b    "NKCC"               ; ID
  325.  
  326.                .if      \?{.oldvec}          ; oldvec defined?
  327.  
  328.                .dc.l    \.oldvec             ; use it
  329.  
  330.                .else                         ; else:
  331.  
  332.                .dc.l    0                    ; use default
  333.  
  334.                .endif
  335.  
  336.                .endm
  337.  
  338.  
  339.  
  340. ****************************************************************************
  341. *                            LOCAL TEXT SECTION                            *
  342. ****************************************************************************
  343.  
  344.                .text
  345.  
  346. ****************************************************************************
  347. *
  348. *  nk_gci: GEMDOS console character input
  349. *  #
  350. *
  351. *  This function returns when
  352. *
  353. *     a) either any key is pressed or
  354. *     b) the Alternate key is released
  355. *
  356. *  The Alternate check can be suppressed by setting the input parameter in
  357. *  D0.W to zero. The routine works then just as a "get key" function.
  358. *
  359. *  In:   D0.W           Alternate key check flag:
  360. *                       zero = don't check it
  361. *                       non-zero = do Alternate check
  362. *
  363. *  Out:  D0.W           key code in normalized format
  364. *                       for details see nkc_tconv()
  365. *        D1.W           flag:
  366. *                       zero = D0.W not valid; Alternate was released
  367. *                       non-zero = D1.W valid; Alternate still pressed
  368. *                          (also returned when Alternate check supressed)
  369. *        CCR            set according content of D1.W
  370. *
  371. *  Reg:  D:01234567   A:01234567   CCR
  372. *          U***....     ****....   =D1.W
  373. *
  374. ****************************************************************************
  375.  
  376. nk_gci:        move     d0,d3                ; Alternate check flag
  377.                beq.s    .getkey              ; no check? just get key
  378.  
  379.                move.l   pshift,a3            ; ^shift key state
  380.  
  381. .loop:         btst.b   #3,(a3)              ; Alternate still pressed?
  382.                beq.s    .abort               ; no->
  383.  
  384.                move     #11,-(sp)            ; Cconis: get key input status
  385.                trap     #1                   ; Gemdos
  386.                addq     #2,sp                ; clean stack
  387.  
  388.                tst      d0                   ; any key pressed?
  389.                beq.s    .loop                ; no->
  390.  
  391. .getkey:       move     #7,-(sp)             ; Crawcin: get key
  392.                trap     #1                   ; Gemdos
  393.                addq     #2,sp                ; clean stack
  394.                bsr      nkc_tconv            ; convert key code
  395.                moveq.l  #-1,d1               ; flag: key code valid
  396.                rts                           ; bye
  397.  
  398. .abort:        moveq.l  #0,d1                ; flag: key code not valid
  399.                rts                           ; bye
  400.  
  401.  
  402.  
  403. ****************************************************************************
  404. *
  405. *  nk_spec: special key code handling
  406. *  #
  407. *
  408. *  nk_spec() performs the special key handling defined by <sflags> (deadkey
  409. *  management, ASCII code input, Control key emulation).
  410. *
  411. *  In:   D0.W           key code in normalized format
  412. *                       for details see nkc_tconv()
  413. *        A0.L           ^function which gets new key codes and checks
  414. *                       the Alternate key state
  415. *                       For the calling conventions consult nk_gci() or
  416. *                       nk_mci(). The function MUST NOT modify the CPU
  417. *                       registers D5-D7 and A5-A6.
  418. *
  419. *  Out:  D0.W           (new) key code in normalized format
  420. *        CCR            set according contents of D0.W
  421. *
  422. *  Reg:  D:01234567   A:01234567   CCR
  423. *          U*******     *******.   =D0.W
  424. *
  425. ****************************************************************************
  426.  
  427. nk_spec:       move.l   a0,a6                ; save ^function
  428.                btst.b   #NKSb_ALTNUM,sflags + 3 ; ASCII input enabled?
  429.                beq.s    .ctrlkey             ; no->
  430.  
  431.  
  432. *------------- ASCII input
  433.  
  434.                moveq.l  #0,d6                ; reset digit counter
  435.                moveq.l  #0,d5                ; reset ASCII code
  436.                bra.s    .isdigit             ; check if valid key
  437.  
  438. .notvalid:     tst      d6                   ; key not valid; first one?
  439.                beq.s    .ctrlkey             ; yes-> exit
  440.  
  441. .getkey:       move     d0,d7                ; save previous key code
  442.                moveq.l  #-1,d0               ; check Alternate
  443.                jsr      (a6)                 ; get key
  444.                beq.s    .makeascii           ; Alternate released? abort loop
  445.  
  446. .isdigit:      move     d0,d1                ; key code
  447.                and      #NKFf_NUM | NKFf_ALT,d1 ; isolate flags
  448.                cmp      #NKFf_NUM | NKFf_ALT,d1 ; with Alternate and numeric?
  449.                bne.s    .notvalid            ; no->
  450.  
  451.                cmp.b    #'0',d0              ; must be in range from 0 ...
  452.                blo.s    .notvalid
  453.  
  454.                cmp.b    #'9',d0              ; ... to 9
  455.                bhi.s    .notvalid
  456.  
  457.                mulu     #10,d5               ; new digit in ASCII code
  458.                sub      #'0',d0              ; ASCII->number
  459.                add      d0,d5                ; add new digit
  460.                addq     #1,d6                ; count digits
  461.                cmp      #3,d6                ; 3rd digit added?
  462.                bne.s    .getkey              ; no-> next key
  463.  
  464. .makeascii:    move     d7,d0                ; previous key code
  465.                and      #NKFf_CAPS,d0        ; isolate CapsLock flag
  466.                move.b   d5,d0                ; add key code (ASCII)
  467.  
  468.  
  469. *------------- Control key emulation
  470.  
  471. .ctrlkey:      btst.b   #NKSb_CTRL,sflags + 3   ; enabled?
  472.                beq.s    .deadkey             ; no ->
  473.  
  474.                btst.l   #NKFb_CTRL,d0        ; Control flag set?
  475.                beq.s    .deadkey             ; no ->
  476.  
  477.                btst.l   #NKFb_ALT,d0         ; Alternate flag set?
  478.                bne.s    .deadkey             ; yes ->
  479.  
  480.                cmp.b    #$40,d0              ; check ASCII code
  481.                blo.s    .deadkey             ; too low ->
  482.  
  483.                cmp.b    #$5f,d0              ; check again
  484.                bhi.s    .deadkey             ; too high ->
  485.  
  486.                                              ; clear function and Control flags
  487.                and      #~(NKFf_FUNC|NKFf_CTRL),d0
  488.                sub.b    #$40,d0              ; new ASCII code
  489.  
  490.  
  491. *------------- check if key = deadkey
  492.  
  493. .deadkey:      tst      d0                   ; function key?
  494.                bmi.s    .ret                 ; yes-> no deadkey
  495.  
  496.                lea      deadtab,a0           ; ^deadkey table
  497.                move     sflags,d4            ; deadkey flags
  498.                beq.s    .exit                ; no deadkeys at all->
  499.  
  500. .finddead:     move     (a0)+,d2             ; get option flag mask
  501.                beq.s    .exit                ; end of table-> no deadkey
  502.  
  503.                move     (a0)+,d1             ; get key code
  504.                addq     #4,a0                ; skip ^match table
  505.                and      d4,d2                ; is this deadkey enabled?
  506.                beq.s    .finddead            ; no ->
  507.  
  508.                cmp.b    d0,d1                ; deadkey found?
  509.                bne.s    .finddead            ; no->
  510.  
  511.  
  512. *------------- key is dead key, get second key and merge them
  513.  
  514.                move.l   -4(a0),a5            ; ^deadkey match table
  515.                move     d0,-(sp)             ; save key code
  516.                clr      d0                   ; no Alternate check
  517.                jsr      (a6)                 ; get second key
  518.                move     sflags,-(sp)         ; save deadkey flags
  519.                clr      sflags               ; disable deadkeys temporary
  520.                move.l   a6,a0                ; do ASCII input/ctrl key check
  521.                bsr      nk_spec              ; by calling myself!
  522.  
  523.                move     (sp)+,sflags         ; restore deadkey flags
  524.                move     (sp)+,d7             ; restore first key code
  525.                tst      d0                   ; function key?
  526.                bmi.s    .nomatch             ; yes-> doesn't match with deadkey
  527.  
  528. .findmatch:    move     (a5)+,d1             ; merged and second key code
  529.                beq.s    .nomatch             ; end of table->
  530.  
  531.                cmp.b    d0,d1                ; second key code found?
  532.                bne.s    .findmatch           ; no->
  533.  
  534.                lsr      #8,d1                ; yes: merged code in .B
  535.                and      #NKFf_CAPS,d0        ; clear all except CapsLock
  536.                move.b   d1,d0                ; CapsLock flag + merged key
  537.                bra.s    .exit                ; exit
  538.  
  539. .nomatch:      move     d0,prvkey            ; save second key
  540.                st.b     prvvalid             ; set validation flag
  541.                move     d7,d0                ; return first key
  542.  
  543. .ret:          rts                           ; bye
  544.  
  545. .exit:         tst      d0                   ; set CCR
  546.                rts                           ; bye
  547.  
  548.  
  549.  
  550. ****************************************************************************
  551. *
  552. *  nk_ascmatch: check if ASCII code matches with one from the key code tables
  553. *  # R
  554. *
  555. *  This functions proofs, if D0.B equals to D4.B, D5.B or D6.B. An according
  556. *  flag is returned. The flag bytes in the TOS key code D0.L are modified
  557. *  depending on which code matches.
  558. *
  559. *  In:   D0.L           key code in TOS format
  560. *        D4.B           ASCII code from unshifted key table
  561. *        D5.B           ASCII code from shifted key table
  562. *        D6.B           ASCII code from CapsLock key table
  563. *
  564. *  Out:  D0.L           key code in TOS format
  565. *                       (updated flags in upper byte)
  566. *
  567. *        CCR            EQ: ASCII code was found
  568. *                       NE: ASCII code wan't found
  569. *
  570. *  Reg:  D:01234567   A:01234567   CCR
  571. *          U......*     ........   flag (see above)
  572. *
  573. ****************************************************************************
  574.  
  575. nk_ascmatch:   tst.b    d0                   ; zero?
  576.                bne.s    .comp                ; no ->
  577.  
  578.                move.l   d0,d7                ; copy key code
  579.                                              ; Alt/Control already found out?
  580.                and.l    #(NKFf_ALT|NKFf_CTRL)<<16,d7
  581.                bne.s    .unknown             ; yes ->
  582.  
  583. .comp:         cmp.b    d4,d0                ; unshifted?
  584.                bne.s    .shftst              ; no ->
  585.  
  586.                cmp.b    d6,d0                ; in CapsLock table, too?
  587.                beq.s    .exit                ; yes ->
  588.  
  589.                bclr.l   #NKFb_CAPS+16,d0     ; no: cannot be CapsLock
  590.                bra.s    .exit                ; ->
  591.  
  592. .shftst:       cmp.b    d5,d0                ; shifted?
  593.                bne.s    .cpstst              ; no ->
  594.  
  595.                cmp.b    d6,d0                ; in CapsLock table, too?
  596.                bne.s    .shifted             ; no ->
  597.  
  598.                btst.l   #NKFb_CAPS+16,d0     ; CapsLock active?
  599.                bne.s    .exit                ; yes -> it COULD be generated
  600.                                              ;  by pressing Shift, but we
  601.                                              ;  assume CapsLock
  602.  
  603. .shifted:      or.l     #NKFf_SHIFT<<16,d0   ; shifted: set both shift flags
  604.                bra.s    .exit                ; ->
  605.  
  606. .cpstst:       cmp.b    d6,d0                ; in CapsLock table?
  607.                bne.s    .unknown             ; no ->
  608.  
  609.                bset.l   #NKFb_CAPS+16,d0     ; yes: set CapsLock flag
  610.  
  611. .exit:         moveq.l  #0,d7                ; found
  612.                rts
  613.  
  614. .unknown:      moveq.l  #1,d7                ; not found
  615.                rts
  616.  
  617.  
  618.  
  619. ****************************************************************************
  620. *
  621. *  nk_findscan: find scan code
  622. *  # R
  623. *
  624. *  The
  625. *
  626. *  In:   D0.W           normalized key code
  627. *        A0.L           ^base of system's key code table
  628. *
  629. *  Out:  D1.W           found scan code (0 = not found)
  630. *        CCR            set according contents of D1.W
  631. *
  632. *  Reg:  D:01234567   A:01234567   CCR
  633. *          .W......     *.......   =D1
  634. *
  635. ****************************************************************************
  636.  
  637. nk_findscan:   btst.l   #NKFb_NUM,d0         ; on numeric keypad?
  638.                beq.s    .search              ; no ->
  639.  
  640.                move     #$4a,d1              ; yes: try all numeric keypad
  641.                cmp.b    (a0,d1),d0           ;  scan codes first
  642.                beq.s    .found               ; it matches ->
  643.  
  644.                move     #$4e,d1
  645.                cmp.b    (a0,d1),d0
  646.                beq.s    .found
  647.  
  648.                move     #$63,d1              ; block starts at $63
  649.  
  650. .numsearch:    cmp.b    (a0,d1),d0           ; match?
  651.                beq.s    .found               ; yes ->
  652.  
  653.                addq     #1,d1                ; next scan code
  654.                cmp      #$73,d1              ; block end at $72
  655.                blo.s    .numsearch           ; continue search ->
  656.  
  657. .search:       move     #1,d1                ; start with first valid scan code
  658.  
  659. .mainsearch:   cmp.b    (a0,d1),d0           ; match?
  660.                beq.s    .found               ; yes ->
  661.  
  662.                addq.b   #1,d1                ; next scan code
  663.                cmp.b    #$78,d1              ; $78 = last valid scan code
  664.                blo.s    .mainsearch          ; continue search ->
  665.  
  666.                moveq.l  #0,d1                ; not found
  667.                rts
  668.  
  669. .found:        tst      d1                   ; found; set CCR
  670.                rts
  671.  
  672.  
  673.  
  674.                .if      NKCGEM=1
  675.  
  676. ****************************************************************************
  677. *
  678. *  nk_bioscode: convert GEM key code to GEMDOS/BIOS format
  679. *  # R
  680. *
  681. *  This is a simple converter which takes key codes in AES format (two
  682. *  words) and transforms them to the BIOS key format (one longword).
  683. *
  684. *  In:   D0.W           key code
  685. *                       high byte = scan code, low byte = ASCII code
  686. *        D1.W           shift key state flags
  687. *                       Bit 0: right Shift
  688. *                       Bit 1: left Shift
  689. *                       Bit 2: Control
  690. *                       Bit 3: Alternate
  691. *
  692. *  Out:  D0.L           key code in BIOS format
  693. *                       for details see nkc_tconv()
  694. *
  695. *  Reg:  D:01234567   A:01234567   CCR
  696. *          U*......     *.......    *
  697. *
  698. ****************************************************************************
  699.  
  700. nk_bioscode:   swap     d0                   ; key code in high word
  701.                move     d1,d0                ; shift key state
  702.                move.l   pshift,a0            ; ^shift key state system variable
  703.                move.b   (a0),d1              ; get it
  704.                and      #~NKFf_CAPS,d1       ; isolate CapsLock flag
  705.                or       d1,d0                ; merge with other shift flags
  706.                swap     d0                   ; shift state in high word
  707.                lsl.l    #8,d0                ; move 'em up
  708.                lsr      #8,d0                ; now key code in BIOS format
  709.                rts                           ; bye
  710.  
  711.  
  712.  
  713. ****************************************************************************
  714. *
  715. *  nk_real_shift: try to get original shift flags of a key code
  716. *  #
  717. *
  718. *  This function uses the contents of the Iorec keyboard ring buffer to
  719. *  restore the original shift flag byte of a key code which has been
  720. *  transported through AES' event manager and thus stripped off its
  721. *  flag byte.
  722. *
  723. *  In:   D0.L           key code in TOS format
  724. *                       for details see nkc_tconv()
  725. *
  726. *  Out:  D0.L           updated key code in TOS format
  727. *
  728. *  Reg:  D:01234567   A:01234567   CCR
  729. *          U**.....     *.......    *
  730. *
  731. ****************************************************************************
  732.  
  733. nk_real_shift: move.l   kbdiorec,a0          ; ^keyboard's I/O record
  734.                movem.l  d3/d4,-(sp)          ; save registers
  735.                move     IBUFHD(a0),d1        ; head pointer
  736.                move     IBUFTL(a0),d2        ; tail pointer
  737.                move     iohead,d3            ; NKCC's head pointer
  738.  
  739.  
  740. *------------- check if tail pointer has overrun NKCC's head pointer
  741.  
  742.                cmp      d1,d2                ; tail < head?
  743.                blo.s    .tlwrap              ; yes -> it has been wrapped around
  744.  
  745.                cmp      d3,d1                ; my tail between record's
  746.                bhs.s    .search              ;  head and tail?
  747.  
  748.                cmp      d2,d3                ; if so, tail has overrun my
  749.                blo.s    .reset               ;  head -> reset
  750.  
  751.                bra.s    .search              ; no overrun ->
  752.  
  753. .tlwrap:       cmp      d2,d3                ; my tail below wrapped record's
  754.                blo.s    .reset               ;  tail pointer or above head?
  755.  
  756.                cmp      d3,d1                ; then tail has overrun my
  757.                blo.s    .reset               ;  head -> reset
  758.  
  759.  
  760. *------------- find key code in ring buffer
  761.  
  762. .search:       move     IBUFSIZ(a0),d2       ; buffer size
  763.                move.l   IBUF(a0),a0          ; ^base of buffer
  764.                move.l   d0,d4                ; copy key code
  765.                swap     d4                   ; scan code in low byte of d4
  766.                bra.s    .find2               ; ->
  767.  
  768. .find:         addq     #4,d3                ; advance to next read-position
  769.                cmp      d2,d3                ; wrap around?
  770.                blo.s    .getkey              ; no ->
  771.  
  772.                moveq.l  #0,d3                ; yes: wrap
  773.  
  774. .getkey:       cmp.b    3(a0,d3),d0          ; compare ASCII code
  775.                bne.s    .find2               ; doesn't match ->
  776.  
  777.                cmp.b    1(a0,d3),d4          ; compare scan code
  778.                bne.s    .find2               ; doesn't match ->
  779.  
  780.                move.l   (a0,d3),d0           ; found: get complete key code
  781.                bra.s    .exit                ; ->
  782.  
  783. .find2:        cmp      d1,d3                ; my head has reached buffer's head
  784.                bne.s    .find                ; no ->
  785.  
  786. .reset:        move     d1,d3                ; reset head pointer
  787.  
  788. .exit:         move     d3,iohead            ; save new head pointer
  789.                movem.l  (sp)+,d3/d4          ; restore registers
  790.                rts                           ; bye
  791.  
  792.  
  793.  
  794. ****************************************************************************
  795. *
  796. *  nk_mci: multi event console character input
  797. *  # U
  798. *
  799. *  This function returns when
  800. *
  801. *     a) either any key is pressed or
  802. *     b) the Alternate key is released
  803. *
  804. *  The Alternate check can be suppressed by setting the input parameter in
  805. *  D0.W to zero. The routine works then just as a "get key" function.
  806. *
  807. *  In:   D0.W           Alternate key check flag:
  808. *                       zero = don't check it
  809. *                       non-zero = do Alternate check
  810. *
  811. *  Out:  D0.W           key code in normalized format
  812. *                       for details see nkc_tconv()
  813. *        D1.W           flag:
  814. *                       zero = D0.W not valid; Alternate was released
  815. *                       non-zero = D1.W valid; Alternate still pressed
  816. *                          (also returned when Alternate check supressed)
  817. *        CCR            set according content of D1.W
  818. *
  819. *  Reg:  D:01234567   A:01234567   CCR
  820. *          U***....     ****....   =D1.W
  821. *
  822. ****************************************************************************
  823.  
  824. nk_mci:        move     d0,d3                ; save Alternate check flag
  825.                move.l   pshift,a3            ; ^shift key state variable
  826.  
  827. .loop:         lea      nkc_contrl,a0        ; ^control array
  828.                move     #25,(a0)+            ; opcode
  829.                move     #16,(a0)+            ; size of intin
  830.                move     #7,(a0)+             ; size of intout
  831.                move     #1,(a0)+             ; size of addrin
  832.                clr      (a0)                 ; size of addrout
  833.  
  834.                lea      nkc_intin,a0         ; ^intin array
  835.                move     #MU_TIMER|MU_KEYBD,(a0) ; wait for timer and key strokes
  836.                clr.l    7*4(a0)              ; waiting time: 0 ms = minimum!
  837.  
  838.                move     #200,d0              ; opcode for AES
  839.                move.l   #aespb,d1            ; ^AES parameter block
  840.                trap     #2                   ; call GEM
  841.  
  842.                lea      nkc_intout,a0        ; ^intout array
  843.                move     (a0),d0              ; event mask
  844.                move.b   (a3),d1              ; shift key state
  845.                and      #$f,d1               ; clear unused bits
  846.                move     #MU_KEYBD,d2         ; did keyboard event occur?
  847.                and      d0,d2                ; check bit
  848.                bne.s    .keybd               ; yes->
  849.  
  850.                move.l   kbdiorec,a1          ; ^keyboard's I/O record
  851.                move     IBUFHD(a1),iohead    ; reset NKCC's head pointer
  852.                tst      d3                   ; do Alternate check?
  853.                beq.s    .loop                ; no->
  854.  
  855.                btst.l   #3,d1                ; Alternate still pressed?
  856.                bne.s    .loop                ; yes->
  857.  
  858.                moveq.l  #0,d1                ; Alternate released: abort
  859.                rts
  860.  
  861. .keybd:        move     10(a0),d0            ; key code
  862.                bsr      nk_bioscode          ; convert to BIOS keycode
  863.                bsr      nk_real_shift        ; try to get original shift flags
  864.                bsr      nkc_tconv            ; convert to normalized format
  865.                moveq.l  #1,d1                ; key code is valid
  866.                rts                           ; bye
  867.  
  868.  
  869.  
  870. ****************************************************************************
  871. *
  872. *  nk_gemtrap: GEM trap handler
  873. *  # S T2
  874. *
  875. *  This function is linked to the GEM trap vector at initialization time.
  876. *  It waits for evnt_dclick() calls (get/set double click time) and saves
  877. *  new click times in an own buffer.
  878. *
  879. *  In:   D0.W           opcode:
  880. *                       115 = VDI
  881. *                       200 = AES
  882. *        A0.L           AES/VDI parameter block
  883. *
  884. *  Out:  -
  885. *
  886. *  Reg:  D:01234567   A:01234567   CCR
  887. *          ..*.....     **......    *
  888. *
  889. ****************************************************************************
  890.  
  891.                XBRA_HD                       ; XBRA header
  892.  
  893. nk_gemtrap:    cmp      #200,d0              ; AES?
  894.                bne.s    .exit                ; no ->
  895.  
  896.                move.l   d1,a0                ; ^parameter block
  897.                move.l   (a0),a1              ; ^contrl array
  898.                cmp      #26,(a1)             ; opcode for evnt_dclick?
  899.                bne.s    .exit                ; no ->
  900.  
  901.                move.l   8(a0),a1             ; ^intin array
  902.                tst      2(a1)                ; set new time?
  903.                beq.s    .exit                ; no ->
  904.  
  905.                move     (a1),d2              ; yes: get new time
  906.                cmp      #4,d2                ; limit check
  907.                bls.s    .save                ; ok: save new value
  908.  
  909.                moveq.l  #4,d2                ; out of range: use maximum
  910.  
  911. .save:         move     d2,bvar+BI_DCLTIME   ; save it
  912.  
  913. .exit:         move.l   nk_gemtrap-4(pc),-(sp)  ; old vector address
  914.                rts                           ; jump to old routine
  915.  
  916.  
  917.  
  918. ****************************************************************************
  919. *
  920. *  nk_butvec: VDI mouse button change handler
  921. *  # I S
  922. *
  923. *  This function handles changes of the mouse button state. It is used
  924. *  for NKCC's own button event handler, which consists mainly of this
  925. *  interrupt and the functions nk_bestart() and nk_beend().
  926. *
  927. *  The handler knows several modes (stored in bvar+BU_BMODE.w):
  928. *
  929. *  0     standby mode: no button event in process, waiting for first click
  930. *  1     wait mode: button event in process, but not yet finished: waiting
  931. *        for a possible second, third ... click
  932. *  2     hold mode: button event was generated, condition still true (buttons
  933. *        are still pressed): repeat button event
  934. *
  935. *  In:   D0.W           current state of mouse buttons
  936. *
  937. *  Out:  D0.W           current state of mouse buttons (unchanged)
  938. *
  939. *  Reg:  D:01234567   A:01234567   CCR
  940. *          ........     ........    *
  941. *
  942. ****************************************************************************
  943.  
  944.                XBRA_HD  nk_bvret             ; XBRA header
  945.  
  946. * Some milliseconds after the installation of this function, the old vector
  947. * address is not set (VDI has to return first). A mouse click during this
  948. * time would lead to a system crash because the new handler jumps through
  949. * this vector. This is the reason why it's initial content points to a
  950. * RTS instruction. (I know, this is a very very improbable situation, but
  951. * it IS possible! And that's reason enough to prepare for it and write
  952. * some silly lines of comment about it!)
  953.  
  954. nk_butvec:     movem.l  d5-d7/a0-a1,-(sp)    ; save registers
  955.                lea      bvar,a1              ; ^button event info block
  956.                move     d0,d7                ; new button mask
  957.                move     BI_BSTATE(a1),d6     ; requested button state
  958.                eor      d6,d7                ; XOR 'em
  959.                move     BI_BMASK(a1),d6      ; button mask
  960.                and      d6,d7                ; isolate valid bits
  961.                tst      BI_REVCOND(a1)       ; condition reverse flag
  962.                bne.s    .rev                 ; reverse ->
  963.  
  964.                tst      d7                   ; 0-> all button conditions true
  965.                seq.b    d6                   ; if so, the set d6 to $ff
  966.                bra.s    .chkmode             ; ->
  967.  
  968. .rev:          eor      d6,d7                ; invert condition flags
  969.                cmp      d6,d7                ; at least one condition true?
  970.                sne.b    d6                   ; yes -> set d6 to $ff
  971.  
  972. * the registers contain now:
  973. *
  974. * d6.b = button condition flag (0=condition false, $ff=condition true)
  975. * d7.w = button condition mask (bits with value 0 indicate true condition)
  976.  
  977. .chkmode:      move.b   d6,BI_CVALID(a1)     ; save flag
  978.                move     BI_BMODE(a1),d5      ; check current mode
  979.                beq.s    .standby             ; standby mode ->
  980.  
  981.                subq     #1,d5                ; check if wait mode
  982.                beq.s    .wait                ; wait mode ->
  983.  
  984.  
  985. *------------- handler is in HOLD mode
  986.  
  987. .hold:         tst.b    d6                   ; hold mode: button condition true?
  988.                beq.s    .reset               ; no ->
  989.  
  990.                move     #1,BI_NCLICKS(a1)    ; 1 mouse click
  991.                move     d0,BI_SBSTATE(a1)    ; use current button state
  992.                st.b     BI_BEVALID(a1)       ; generate mouse click
  993.                bra      .exit
  994.  
  995. .reset:        clr      BI_BMODE(a1)         ; switch to standby mode
  996.                bra.s    .exit
  997.  
  998.  
  999. *------------- handler is in STANDBY mode
  1000.  
  1001. .standby:      tst.b    BI_BEVALID(a1)       ; old click still in buffer?
  1002.                bne.s    .exit                ; yes ->
  1003.  
  1004.                tst.b    d6                   ; button condition true?
  1005.                beq.s    .exit                ; no ->
  1006.  
  1007.                move     d0,BI_SBSTATE(a1)    ; save button state
  1008.                moveq.l  #1,d5
  1009.                move     d5,BI_BMODE(a1)      ; change to wait mode
  1010.                move     d5,BI_NCLICKS(a1)    ; init # of clicks
  1011.  
  1012.                lea      timetab,a0           ; ^double click time table
  1013.                move     BI_DCLTIME(a1),d5    ; double click time
  1014.                add      d5,d5                ; *4 for index
  1015.                add      d5,d5
  1016.                move.l   (a0,d5),d5           ; get double click time
  1017.                add.l    sysclock,d5          ; add current timer value
  1018.                move.l   d5,BI_BENDTIME(a1)   ; save as end time
  1019.  
  1020.                moveq.l  #1,d5                ; find first button
  1021.  
  1022. .findbut:      add      d5,d5                ; next button
  1023.                lsr      d7                   ; check next bit
  1024.                bcs.s    .findbut             ; condition not true ->
  1025.  
  1026.                lsr      d5                   ; first found changed button
  1027.  
  1028. .dcbut:        move     d5,BI_DCBUT(a1)      ; save double click button mask
  1029.                and      d0,d5                ; get 'active' state
  1030.                move     d5,BI_DCSTATE(a1)    ; save it
  1031.  
  1032.                bra.s    .exit                ; ->
  1033.  
  1034.  
  1035. *------------- handler is in WAIT mode
  1036.  
  1037. .wait:         tst.b    BI_BEVALID(a1)       ; old click still in buffer?
  1038.                bne.s    .exit                ; yes ->
  1039.  
  1040.                move     BI_DCBUT(a1),d5      ; double click button mask
  1041.                move     BI_PRVBSTATE(a1),d7  ; previous button state
  1042.                eor      d0,d7                ; get button state changes
  1043.                and      d5,d7                ; did dclick button state change?
  1044.                beq.s    .exit                ; no ->
  1045.  
  1046.                and      d0,d5                ; isolate state of dclick button
  1047.                cmp      BI_DCSTATE(a1),d5    ; changed it to 'active' state?
  1048.                bne.s    .exit                ; no ->
  1049.  
  1050.                moveq.l  #1,d7                ; yes: add 1 to # of clicks
  1051.                add      BI_NCLICKS(a1),d7
  1052.                cmp      BI_MAXCLICKS(a1),d7  ; > max # of clicks to wait for?
  1053.                bhi.s    .exit                ; yes ->
  1054.  
  1055.                move     d7,BI_NCLICKS(a1)    ; no: save new # of clicks
  1056.                add.l    #TIME_ADD,BI_BENDTIME(a1)  ; let user more time to click
  1057.  
  1058.  
  1059. *------------- leave interrupt
  1060.  
  1061. .exit:         move     d0,BI_PRVBSTATE(a1)  ; save button state
  1062.                movem.l  (sp)+,d5-d7/a0-a1    ; restore registers
  1063.                move.l   nk_butvec-4(pc),-(sp)   ; old vector address
  1064.  
  1065. nk_bvret:      rts                           ; jump to old routine
  1066.  
  1067.  
  1068.  
  1069.  
  1070. ****************************************************************************
  1071. *
  1072. *  nk_bestart: start special handling of button event
  1073. *  #
  1074. *
  1075. *  In:   -
  1076. *
  1077. *  Out:  D7.W           handler mode (used in nk_beend)
  1078. *
  1079. *  Reg:  D:01234567   A:01234567   CCR
  1080. *          **.....W     **......    *
  1081. *
  1082. ****************************************************************************
  1083.  
  1084. nk_bestart:    moveq.l  #0,d7                ; default: no special handling
  1085.                tst.b    buthnd               ; our handler installed?
  1086.                beq      .exit                ; no ->
  1087.  
  1088.                lea      nkc_intin,a0         ; ^event mask
  1089.                moveq.l  #MU_BUTTON,d0        ; request for button event?
  1090.                and      (a0),d0
  1091.                beq      .exit                ; no ->
  1092.  
  1093.  
  1094. *------------- configure timer event
  1095.  
  1096.                lea      bvar,a1              ; ^button event variables
  1097.                move     2(a0),d7             ; nclicks + reverse flag
  1098.                move.b   d7,BI_MAXCLICKS+1(a1)   ; isolate and save nclicks
  1099.                clr.b    d7                   ; isolate reverse flag
  1100.                move     d7,BI_REVCOND(a1)    ; save reverse flag
  1101.                move     4(a0),BI_BMASK(a1)   ; save button mask
  1102.                move     6(a0),BI_BSTATE(a1)  ; save button state
  1103.                                              ; new mouse button parameters:
  1104.                clr      4(a0)                ; mask = 0
  1105.                clr      6(a0)                ; state = 0
  1106.                moveq.l  #1,d7                ; new handler mode
  1107.                move     d7,2(a0)             ; also used for new nclicks
  1108.                                              ; -> button condition always true
  1109.  
  1110. *------------- configure timer event
  1111.  
  1112.                moveq.l  #MU_TIMER,d0         ; request for timer event?
  1113.                and      (a0),d0
  1114.                beq.s    .no_timer            ; no ->
  1115.  
  1116.                moveq.l  #2,d7                ; new mode
  1117.                move.l   28(a0),d0            ; time = 0 ms?
  1118.                beq.s    .exit                ; yes: fine, exactly what we need
  1119.  
  1120.                moveq.l  #3,d7                ; new mode
  1121.                swap     d0                   ; time in Motorola format
  1122.                cmp.l    prvtime,d0           ; identical to previous time?
  1123.                beq.s    .nulltime            ; yes ->
  1124.  
  1125.                move.l   d0,prvtime           ; no: save timer event value
  1126.                LWDIVU   #5,d0,d1             ; convert to 200 Hz resolution
  1127.                add.l    sysclock,d0          ; + current timer value
  1128.                move.l   d0,tendtime          ; this is our timer end value
  1129.  
  1130.                bra.s    .nulltime            ; and set own one
  1131.  
  1132.  
  1133. *------------- user doesn't want timer events - but we need them!
  1134.  
  1135. .no_timer:     moveq.l  #-1,d0               ; reset previous timer event value
  1136.                move.l   d0,prvtime
  1137.                or       #MU_TIMER,(a0)       ; set bit: check timer events
  1138.  
  1139. .nulltime:     clr.l    28(a0)               ; time: 0 ms
  1140.  
  1141. .exit:         rts                           ; bye
  1142.  
  1143.  
  1144.  
  1145.  
  1146. ****************************************************************************
  1147. *
  1148. *  nk_beend: end special handling of button event
  1149. *  #
  1150. *
  1151. *  In:   D7.W           handler mode:
  1152. *                       0     button event handler inactive
  1153. *                       1     user did not check timer events
  1154. *                       2     user did check timer events with time = 0 ms
  1155. *                       3     user did check timer events with time > 0 ms
  1156. *
  1157. *  Out:  nkc_intout.W[]:updated mouse event information
  1158. *
  1159. *  Reg:  D:01234567   A:01234567   CCR
  1160. *          **......     **......    *
  1161. *
  1162. ****************************************************************************
  1163.  
  1164. nk_beend:      lea      nkc_intout,a0        ; ^event mask
  1165.                move     d7,d0                ; which mode?
  1166.                beq      .exit                ; no special handling
  1167.  
  1168.                lea      bvar,a1              ; ^button event info block
  1169.                move     BI_PRVBSTATE(a1),6(a0)  ; return button state
  1170.  
  1171.  
  1172. *------------- analyze which events have occured
  1173.  
  1174.                moveq.l  #MU_MESAG,d1         ; did message event occur?
  1175.                and      (a0),d1              ; and with event mask
  1176.                beq.s    .chkflag             ; no message event ->
  1177.  
  1178.                and      #~MU_BUTTON,(a0)     ; no button event
  1179.  
  1180. .chkflag:      moveq.l  #MU_BUTTON,d1        ; did button event occur?
  1181.                and      (a0),d1              ; (if not: just moving a window
  1182.                                              ;  or something like that)
  1183.                beq.s    .lock                ; no -> lock mouse button event
  1184.  
  1185.  
  1186. *------------- application has mouse under its control; what now?
  1187.  
  1188.                tst.b    BI_LOCK(a1)          ; is button event locked?
  1189.                bne      .unlock              ; yes -> unlock it
  1190.  
  1191.                tst.b    BI_BEVALID(a1)       ; event valid?
  1192.                bne.s    .butev               ; yes ->
  1193.  
  1194.  
  1195. *------------- mouse click isn't finished, yet; wait
  1196.  
  1197.                move     BI_BMODE(a1),d1      ; no: get handler mode
  1198.                beq.s    .nombut              ; standby mode ->
  1199.  
  1200.                subq     #1,d1                ; wait mode?
  1201.                beq.s    .wait                ; yes ->
  1202.  
  1203. .hold:         clr      12(a0)               ; # of clicks = 0
  1204.                bra.s    .evtimer
  1205.  
  1206. .wait:         move.l   BI_BENDTIME(a1),d1   ; button event end time
  1207.                cmp.l    sysclock,d1          ; end of time reached?
  1208.                bhi.s    .nombut              ; no ->
  1209.  
  1210.                addq     #1,BI_BMODE(a1)      ; change to hold mode
  1211.                tst.b    BI_CVALID(a1)        ; was last button condition valid?
  1212.                bne.s    .butev               ; yes ->
  1213.  
  1214.                clr      BI_BMODE(a1)         ; no: standby mode
  1215.  
  1216. .butev:        move     BI_NCLICKS(a1),12(a0)   ; return # of clicks
  1217.                move     BI_SBSTATE(a1),6(a0)    ; return start button state
  1218.                sf.b     BI_BEVALID(a1)       ; button event fetched
  1219.                bra.s    .evtimer
  1220.  
  1221. .nombut:       and      #~MU_BUTTON,(a0)     ; no mouse button event
  1222.  
  1223.  
  1224. *------------- timer event handling
  1225.  
  1226. .evtimer:      subq     #1,d0                ; timer event checked by us?
  1227.                beq.s    .nktimer             ; yes ->
  1228.  
  1229.                subq     #1,d0                ; 0 ms timer checked by user?
  1230.                beq.s    .exit                ; yes ->
  1231.  
  1232. .user0:        move.l   tendtime,d1          ; timer event end time
  1233.                cmp.l    sysclock,d1          ; end of waiting time reached?
  1234.                bls.s    .exit                ; yes ->
  1235.  
  1236. .nktimer:      and      #~MU_TIMER,(a0)      ; no timer event occured
  1237.  
  1238. .exit:         move     (a0),d0              ; event mask
  1239.                and      #MU_TIMER,d0         ; did a timer event occur?
  1240.                beq.s    .exit2               ; no ->
  1241.  
  1242. .treset:       moveq.l  #-1,d0               ; yes: reset previous timer
  1243.                move.l   d0,prvtime           ;  event value
  1244.  
  1245. .exit2:        rts
  1246.  
  1247.  
  1248. *------------- AES didn't return MU_BUTTON -> screen manager has taken mouse
  1249. *              control: don't create MU_BUTTON events
  1250.  
  1251. .lock:         st.b     BI_LOCK(a1)          ; lock mouse button event
  1252.                move     #MU_XTIMER,d1        ; lock timer events, too?
  1253.                and      nkc_intin,d1         ; check this flag
  1254.                beq.s    .evtimer             ; don't lock ->
  1255.  
  1256.                bra.s    .nktimer             ; lock ->
  1257.  
  1258.  
  1259. *------------- AES did return MU_BUTTON (applications has mouse under its
  1260. *              control) but the button events were locked previously: unlock
  1261. *              them
  1262.  
  1263. .unlock:       sf.b     BI_LOCK(a1)          ; unlock mouse button event
  1264.                clr      BI_BMODE(a1)         ; reset mode
  1265.                sf.b     BI_BEVALID(a1)       ; reset button event flag
  1266.                bra.s    .nombut
  1267.  
  1268.  
  1269.  
  1270. ****************************************************************************
  1271. *
  1272. *  nk_mctrl: set control array for multi event
  1273. *  #
  1274. *
  1275. *  In:   -
  1276. *
  1277. *  Out:  nkc_contrl.W[]: control parameters configured for evnt_multi() call
  1278. *
  1279. *  Reg:  D:01234567   A:01234567   CCR
  1280. *          ........     *.......    *
  1281. *
  1282. ****************************************************************************
  1283.  
  1284. nk_mctrl:      lea      nkc_contrl,a0        ; ^control array
  1285.                move     #25,(a0)+            ; opcode
  1286.                move     #16,(a0)+            ; size of intin
  1287.                move     #7,(a0)+             ; size of intout
  1288.                move     #1,(a0)+             ; size of addrin
  1289.                clr      (a0)                 ; size of addrout
  1290.                rts                           ; bye
  1291.  
  1292.  
  1293.  
  1294.  
  1295. ****************************************************************************
  1296. *
  1297. *  nk_msave: save input parameters for evnt_multi() call in buffer
  1298. *  #
  1299. *
  1300. *  In:   -
  1301. *
  1302. *  Out:  multibuf.W[]:  first 16 words of nkc_intin and first long of
  1303. *                          nkc_adrin
  1304. *
  1305. *  Reg:  D:01234567   A:01234567   CCR
  1306. *          *******.     **......    *
  1307. *
  1308. ****************************************************************************
  1309.  
  1310. nk_msave:      lea      nkc_intin,a0         ; ^intin array
  1311.                lea      multibuf,a1          ; ^save buffer
  1312.                movem.l  (a0)+,d0-d6          ; get first 14 words of nkc_intin
  1313.                movem.l  d0-d6,(a1)           ; save 'em in buffer
  1314.                move.l   (a0),7*4(a1)         ; save last two words
  1315.                move.l   nkc_adrin,8*4(a1)    ; save contents of addrin
  1316.                rts
  1317.  
  1318.  
  1319.  
  1320.  
  1321. ****************************************************************************
  1322. *
  1323. *  nk_mrestore: restore evnt_multi() input parameters corrupted by AES(!)
  1324. *  #
  1325. *
  1326. *  In:   -
  1327. *
  1328. *  Out:  nkc_contrl.w[]: restored data (5 words)
  1329. *        nkc_intin.w[] : restored data (16 words)
  1330. *        nkc_adrin.L[] : restored data (1 longword)
  1331. *
  1332. *  Reg:  D:01234567   A:01234567   CCR
  1333. *          *******.     **......    *
  1334. *
  1335. ****************************************************************************
  1336.  
  1337. nk_mrestore:   lea      multibuf,a0          ; ^save buffer
  1338.                lea      nkc_intin,a1         ; ^intin array
  1339.                movem.l  (a0)+,d0-d6          ; first 14 words of nkc_intin
  1340.                movem.l  d0-d6,(a1)           ; put them in nkc_intin array
  1341.                move.l   (a0)+,7*4(a1)        ; last two words
  1342.                move.l   (a0),nkc_adrin       ; restore addrin array
  1343.                bra.s    nk_mctrl             ; restore contrl array
  1344.  
  1345.                .endif   ; .if NKCGEM=1
  1346.  
  1347.  
  1348.  
  1349.  
  1350. ****************************************************************************
  1351. *
  1352. *  nk_200hz: 200 Hz system clock interrupt
  1353. *  # I S
  1354. *
  1355. *  In:   -
  1356. *
  1357. *  Out:  -
  1358. *
  1359. *  Reg:  D:01234567   A:01234567   CCR
  1360. *          ........     ........    *
  1361. *
  1362. ****************************************************************************
  1363.  
  1364.                XBRA_HD                       ; XBRA header
  1365.  
  1366. nk_200hz:      move.l   _hz_200,sysclock     ; just transfer value
  1367.                move.l   nk_200hz-4(pc),-(sp) ; old vector address
  1368.                rts                           ; jump to old routine
  1369.  
  1370.  
  1371.  
  1372. *START
  1373. ****************************************************************************
  1374. *                            GLOBAL TEXT SECTION                           *
  1375. ****************************************************************************
  1376. *END
  1377.  
  1378.                .text
  1379.  
  1380. *START
  1381. ****************************************************************************
  1382. *
  1383. *  nkc_init: initialize NKCC
  1384. *  # G U
  1385. *
  1386. *  This function initializes NKCC. It must be called once before any other
  1387. *  NKCC routine. It performs some tasks that may be important for you to
  1388. *  know:
  1389. *
  1390. *  - bit 3 of the system variable <conterm> ($484.B) is set
  1391. *  - a 200 Hz clock interrupt is installed, using the XBRA method (ID is
  1392. *    "NKCC")
  1393. *
  1394. *  nkc_init() gets some flags which configure NKCC and enable some special
  1395. *  functions:
  1396. *
  1397. *  NKI?_BUTHND       install NKCC's button event handler (see documentation
  1398. *                    NKCC.DOC for details)
  1399. *  NKI?_BHTOS        additional flag: install only, if TOS has mouse click bug
  1400. *  NKI?_NO200HZ      don't install the 200 Hz timer interrupt
  1401. *
  1402. *  Notes:
  1403. *
  1404. *  - if NKCC is assembled as TOS-only version (symbol NKCGEM set to 0),
  1405. *    both NKI?_BUTHND and NKI?_BHTOS flags are ignored.
  1406. *
  1407. *  - if the button event handler is installed, the NKI?_NO200HZ flag is
  1408. *    ignored (because the 200 Hz clock is needed by the handler). Besides,
  1409. *    the initialization continues:
  1410. *
  1411. *    - an own GEM trap handler (trap #2) is installed, using the XBRA method
  1412. *      (to be up to date when a new double click time is set via the AES
  1413. *      function evnt_dclick())
  1414. *
  1415. *    - a vex_butv() call (VDI) is made to install a mouse button exchange
  1416. *      handler
  1417. *
  1418. *  In:   D0.L           miscellaneous flags (NKI?_...); see above
  1419. *        D1.W           handle of an open VDI workstation
  1420. *                       (must only be valid if the button handler is
  1421. *                       installed)
  1422. *        A0.L           ^applications GLOBAL array (from GEM parameter block)
  1423. *                       not used in the TOS version of NKCC
  1424. *
  1425. *  Out:  D0.W           NKCC's version number as 4 digit BCD
  1426. *                       (main # in high byte, sub # in low byte)
  1427. *
  1428. *  Reg:  D:01234567   A:01234567   CCR
  1429. *          U**.....     **......    *
  1430. *
  1431. ****************************************************************************
  1432. *END
  1433.  
  1434. nkc_init:      move.l   a2,-(sp)             ; save a2 for Turbo C/Pure C
  1435.  
  1436.                movem.l  d0-d1,-(sp)          ; save flags and VDI handle
  1437.                subq.l   #2,sp                ; one word local stack space
  1438.  
  1439.                .if      NKCGEM=1
  1440.  
  1441.                 move.l  a0,aespb+4           ; keep ^global array
  1442.  
  1443.                 move    #1,-(sp)             ; device: keyboard
  1444.                 move    #14,-(sp)            ; function opcode: Iorec
  1445.                 trap    #14                  ; XBIOS
  1446.                 addq.l  #4,sp                ; clean stack
  1447.                 move.l  d0,kbdiorec          ; keep ^IOREC structure
  1448.                 move.l  d0,a0                ; load into address register
  1449.                 move    IBUFHD(a0),iohead    ; keep current head pointer
  1450.  
  1451.                .endif   ; .if NKCGEM=1
  1452.  
  1453.  
  1454. *------------- switch to Supervisor mode to have access to system variables
  1455.  
  1456.                clr.l    -(sp)                ; use usp as ssp
  1457.                move     #$20,-(sp)           ; Super
  1458.                trap     #1                   ; GEMDOS
  1459.                move.l   d0,2(sp)             ; save old sp
  1460.                move     #$20,(sp)            ; Super opcode for next call
  1461.  
  1462.  
  1463. *------------- enable auto return of shift/ctrl/alt status
  1464.  
  1465.                bset.b   #3,conterm.w         ; set bit for auto shift return
  1466.  
  1467.  
  1468. *------------- locate shift state system variable
  1469.  
  1470.                move.l   _sysbase.w,a0        ; ^OS header
  1471.                move     2(a0),d0             ; get TOS version
  1472.                move     d0,6(sp)             ; save it in local stack space
  1473.                cmp      #$0100,d0            ; TOS 1.0?
  1474.                beq.s    .tos10               ; yes ->
  1475.  
  1476.                move.l   $24(a0),pshift       ; get ^shift state variable
  1477.                bra.s    .user                ; ->
  1478.  
  1479. .tos10:        move.l   #$e1b,pshift         ; this is the location in TOS 1.0
  1480.  
  1481.  
  1482. *------------- switch back to user mode
  1483.  
  1484. .user:         trap     #1                   ; GEMDOS
  1485.                addq     #6,sp                ; clean stack
  1486.  
  1487.  
  1488. *------------- fetch addresses of TOS' key scan code translation tables
  1489.  
  1490.                moveq.l  #-1,d0               ; the function is also used to
  1491.                move.l   d0,-(sp)             ;  change the addresses; values
  1492.                move.l   d0,-(sp)             ;  of -1 as new addresses tell
  1493.                move.l   d0,-(sp)             ;  XBIOS not to change them
  1494.                move     #$10,-(sp)           ; Keytbl
  1495.                trap     #14                  ; XBIOS
  1496.                lea      $e(sp),sp            ; clean stack
  1497.  
  1498.                move.l   d0,a0                ; ^key table structure
  1499.                move.l   (a0)+,pkey_unshift   ; get ^unshifted table
  1500.                move.l   (a0)+,pkey_shift     ; get ^shift table
  1501.                move.l   (a0),pkey_caps       ; get ^CapsLock table
  1502.  
  1503.  
  1504. *------------- do some other initialization stuff
  1505.  
  1506.                clr.l    sflags               ; reset special key flags
  1507.                clr.b    prvvalid             ; no previous key code
  1508.  
  1509.  
  1510. *------------- install the mouse button handler
  1511.  
  1512.                move     (sp)+,d0             ; TOS version
  1513.                movem.l  (sp),d1-d2           ; restore flags and VDI handle
  1514.  
  1515.                .if      NKCGEM=1
  1516.  
  1517.                 clr.b   buthnd               ; default: set flag: not installed
  1518.                 btst.l  #NKIb_BUTHND,d1      ; install it?
  1519.                 beq     .timer               ; no ->
  1520.  
  1521.                 btst.l  #NKIb_BHTOS,d1       ; check TOS version number?
  1522.                 beq.s   .butev               ; no ->
  1523.  
  1524.                 cmp     #$0104,d0            ; bug appeared in TOS 1.04!
  1525.                 blo     .timer               ; TOS is ok ->
  1526.  
  1527.                 cmp     #$0306,d0            ; bug is solved since TOS 3.06!
  1528.                 bhs     .timer               ; TOS is ok ->
  1529.  
  1530. .butev:         bclr.l  #NKIb_NO200HZ,d1     ; must install timer interrupt
  1531.                 st.b    buthnd               ; set flag: handler installed
  1532.                 move    d2,vdihnd            ; save VDI handle
  1533.  
  1534.                 moveq.l #0,d0                ; do some initializations
  1535.                 lea     bvar,a1              ; ^button event info block
  1536.                 move    d0,BI_BMODE(a1)      ; init interrupt mode
  1537.                 move.b  d0,BI_BEVALID(a1)    ; mouse click info not valid
  1538.                 move    d0,BI_PRVBSTATE(a1)  ; init previous button state
  1539.                 move    d0,BI_BMASK(a1)      ; don't check any button
  1540.                 move.b  d0,BI_LOCK(a1)       ; mouse button event isn't locked
  1541.                 subq.l  #1,d0                ; d0.l = -1
  1542.                 move    d0,BI_REVCOND(a1)    ; reverse button condition
  1543.                                              ; -> no mouse click is checked
  1544.                 move.l  d0,prvtime           ; previous timer event value
  1545.  
  1546.                 lea     nkc_contrl,a0        ; set parameter array for vex_butv
  1547.                 move    #125,(a0)+           ; opcode
  1548.                 clr.l   (a0)+                ; no ptsin/ptsout entries
  1549.                 clr.l   (a0)+                ; no intin/intout entries
  1550.                 addq    #2,a0                ; entry #5 is unused
  1551.                 move    d2,(a0)+             ; handle of workstation
  1552.                 lea     nk_butvec(pc),a1     ; ^our handler
  1553.                 move.l  a1,(a0)
  1554.                 moveq.l #115,d0              ; opcode: VDI
  1555.                 move.l  #vdipb,d1            ; ^parameter block
  1556.                 trap    #2                   ; execute VDI
  1557.                 move.l  nkc_contrl+18,nk_butvec-4  ; save old handler address
  1558.  
  1559.                 lea     nkc_contrl,a0        ; set parameter for evnt_dclick
  1560.                 move    #26,(a0)+            ; opcode
  1561.                 move    #2,(a0)+             ; # of entries in intin
  1562.                 move    #1,(a0)+             ; # of entries in intout
  1563.                 clr.l   (a0)+                ; no entries in addrin/addrout
  1564.                 clr     nkc_intin+2          ; get/set flag: get value
  1565.                 move    #200,d0              ; opcode for AES
  1566.                 move.l  #aespb,d1            ; ^parameter block
  1567.                 trap    #2                   ; execute AES
  1568.                 move    nkc_intout,bvar+BI_DCLTIME    ; save double click time
  1569.  
  1570.                                              ; install trap #2 handler
  1571.                 moveq.l #34,d0               ; vector number
  1572.                 moveq.l #NKXM_NUM,d1         ; mode: vector number
  1573.                 lea     nk_gemtrap(pc),a0    ; ^function to install
  1574.                 bsr     nkc_vlink            ; install it
  1575.  
  1576.                .endif   ; .if NKCGEM=1
  1577.  
  1578.  
  1579. *------------- install 200 Hz clock interrupt
  1580.  
  1581. .timer:        clr.l    sysclock             ; init 200 Hz clock for the case
  1582.                                              ; that the timer won't be installed
  1583.                movem.l  (sp)+,d1-d2          ; restore flags and VDI handle
  1584.                btst.l   #NKIb_NO200HZ,d1     ; install interrupt?
  1585.                seq.b    timerflag            ; $00 = no, $ff = yes
  1586.                bne.s    .exit                ; no ->
  1587.  
  1588.                moveq.l  #69,d0               ; vector number
  1589.                moveq.l  #NKXM_NUM,d1         ; mode: vector number
  1590.                lea      nk_200hz(pc),a0      ; ^function to install
  1591.                bsr      nkc_vlink            ; install it
  1592.  
  1593.  
  1594. *------------- restore saved register and exit
  1595.  
  1596. .exit:         move.l   (sp)+,a2             ; restore register
  1597.                move     #VERSION,d0          ; load version #
  1598.                rts                           ; bye
  1599.  
  1600.  
  1601.  
  1602. *START
  1603. ****************************************************************************
  1604. *
  1605. *  nkc_exit: exit NKCC
  1606. *  # G U
  1607. *
  1608. *  nkc_exit() must be called before the program is quit. It removes all
  1609. *  handlers installed in the system.
  1610. *
  1611. *  In:   -
  1612. *
  1613. *  Out:  D0.W           status flag:
  1614. *                       0     OK
  1615. *                       -1    can't remove 200 Hz clock interrupt
  1616. *                       -2    can't remove trap #2 handler
  1617. *                       -3    can't remove both handlers
  1618. *                       An error can happen if somebody corrupted the
  1619. *                       XBRA vector list. This is fatal!
  1620. *
  1621. *  Reg:  D:01234567   A:01234567   CCR
  1622. *          ***.....     **......   =D0.W
  1623. *
  1624. ****************************************************************************
  1625. *END
  1626.  
  1627. nkc_exit:      move.l   a2,-(sp)             ; save register
  1628.  
  1629.  
  1630. *------------- remove 200 Hz system clock interrupt
  1631.  
  1632.                clr      -(sp)                ; default remove status for
  1633.                                              ;  timer interrupt
  1634.                tst.b    timerflag            ; installed?
  1635.                beq.s    .buthnd              ; no ->
  1636.  
  1637.                moveq.l  #69,d0               ; vector number
  1638.                moveq.l  #NKXM_NUM,d1         ; mode: vector number
  1639.                lea      nk_200hz(pc),a0      ; ^function to remove
  1640.                bsr      nkc_vunlink          ; remove it
  1641.                move     d0,(sp)              ; save remove status
  1642.  
  1643.  
  1644. *------------- remove own button event handler
  1645.  
  1646. .buthnd:       clr      -(sp)                ; default remove status for
  1647.                                              ;  button event handler
  1648.  
  1649.                .if      NKCGEM=1
  1650.  
  1651.                tst.b    buthnd               ; handler installed?
  1652.                beq.s    .exit                ; no ->
  1653.  
  1654.                lea      nkc_contrl,a0        ; set paremeter array for vex_butv
  1655.                move     #125,(a0)+           ; opcode
  1656.                clr.l    (a0)+                ; no ptsin/ptsout entries
  1657.                clr.l    (a0)+                ; no intin/intout entries
  1658.                addq     #2,a0                ; entry #5 is unused
  1659.                move     vdihnd,(a0)+         ; handle of workstation
  1660.                lea      nk_butvec(pc),a1     ; ^our handler
  1661.                move.l   -4(a1),(a0)          ; ^old routine
  1662.                moveq.l  #115,d0              ; opcode: VDI
  1663.                move.l   #vdipb,d1            ; ^parameter block
  1664.                trap     #2                   ; execute VDI
  1665.  
  1666.                                              ; remove trap #2 handler
  1667.                moveq.l  #34,d0               ; vector number
  1668.                moveq.l  #NKXM_NUM,d1         ; mode: vector number
  1669.                lea      nk_gemtrap(pc),a0    ; ^function to remove
  1670.                bsr      nkc_vunlink          ; remove it
  1671.                move     d0,(sp)              ; save status
  1672.  
  1673.                .endif   ; .if NKCGEM=1
  1674.  
  1675.  
  1676. *------------- restore saved registers and exit
  1677.  
  1678. .exit:         move     (sp)+,d0             ; trap #2 remove error?
  1679.                beq.s    .stat0               ; no ->
  1680.  
  1681.                move     (sp)+,d0             ; 200 Hz clock remove error?
  1682.                beq.s    .stat1               ; no ->
  1683.  
  1684.                moveq.l  #-3,d0               ; both failed!
  1685.                bra.s    .ret
  1686.  
  1687. .stat0:        move     (sp)+,d0             ; 200 Hz clock remove error?
  1688.                beq.s    .ret                 ; no ->
  1689.  
  1690.                moveq.l  #-1,d0               ; "only" 200 Hz clock failure?
  1691.                bra.s    .ret
  1692.  
  1693. .stat1:        moveq.l  #-2,d0               ; "only" trap #2 remove failure?
  1694.  
  1695. .ret:          move.l   (sp)+,a2             ; restore register
  1696.                rts                           ; bye
  1697.  
  1698.  
  1699.  
  1700. *START
  1701. ****************************************************************************
  1702. *
  1703. *  nkc_set: set special key flags
  1704. *  # G
  1705. *
  1706. *  This function is used to enable/disable special key handling procedures.
  1707. *  The features which can be set are:
  1708. *
  1709. *  - direct input of ASCII codes; when switched on, pressing the Alternate
  1710. *    key plus one of the numbers on the numeric keypad will start the input
  1711. *    of a decimal ASCII number. The input is finished either when 3 digits
  1712. *    are typed in or the Alternate key is released. NKCC will return the
  1713. *    corresponding character with the entered ASCII code. This feature makes
  1714. *    it possible to use the whole range of the character set (from 0 ... 255).
  1715. *
  1716. *  - deadkey management; when switched on, NKCC will combine some combi-
  1717. *    nations of two key strokes to one character. This is used to generate
  1718. *    characters with accents which are not on the keyboard. The supported
  1719. *    deadkeys are:
  1720. *
  1721. *    ^   +   aeiou      =  âêîôû       (NKS?_D_CIRCUM)
  1722. *    ~   +   nNaoAo     =  ñÑãõÃÕ      (NKS?_D_TILDE)
  1723. *    '   +   eEaiou     =  éÉáíóú      (NKS?_D_AGUI)
  1724. *    `   +   aeiouA     =  àèìòùÀ      (NKS?_D_GRAVE)
  1725. *    ¨   +   aeiouyAOU  =  äëïöüÿÄÖÜ   (NKS?_D_UMLAUT)
  1726. *    "   +   aeiouyAOU  =  äëïöüÿÄÖÜ   (NKS?_D_QUOTE)
  1727. *    °   +   aA         =  åÅ          (NKS?_D_SMOERE)
  1728. *    ,   +   cC         =  çÇ          (NKS?_D_CEDIL)
  1729. *    /   +   oO24       =  øØ½¼        (NKS?_D_SLASH)
  1730. *
  1731. *    The quote character as synonym for umlaut is e.g. needed on the Dutch
  1732. *    keyboard, where neither umlaut characters nor the umlaut itself are
  1733. *    available.
  1734. *
  1735. *    Each deadkey can be enabled/disabled separately.
  1736. *
  1737. *  - Control key emulation: Control plus an ASCII code in the range of
  1738. *    $40...$5F (characters @, A...Z, [, \, ], ^ and _) is converted
  1739. *    to an ASCII code of $00...$1F.
  1740. *
  1741. *
  1742. *  In:   D0.L           new key flags (bit set = feature on):
  1743. *                       NKS?_ALTNUM       ASCII input
  1744. *                       NKS?_D_...        deadkey ...
  1745. *                                         (NKSf_DEADKEY: all deadkeys)
  1746. *                       NKS?_CTRL         control key emulation
  1747. *
  1748. *  Out:  -
  1749. *
  1750. *  Reg:  D:01234567   A:01234567   CCR
  1751. *          ***.....     **......    *
  1752. *
  1753. ****************************************************************************
  1754. *END
  1755.  
  1756. nkc_set:       move.l   d0,sflags            ; just save flags
  1757.                rts                           ; bye
  1758.  
  1759.  
  1760.  
  1761. *START
  1762. ****************************************************************************
  1763. *
  1764. *  nkc_conin: raw console character input
  1765. *  # G
  1766. *
  1767. *  This routine replaces the Gemdos function Crawcin. However, it returns
  1768. *  a WORD with the key code in normalized format rather than a LONG with
  1769. *  the key code in the language dependend TOS format.
  1770. *
  1771. *  In:   -
  1772. *
  1773. *  Out:  D0.W           key code in normalized format
  1774. *                       for details see nkc_tconv()
  1775. *        CCR            set according content of D0.W
  1776. *
  1777. *  Reg:  D:01234567   A:01234567   CCR
  1778. *          W**.....     **......   =D0.W
  1779. *
  1780. ****************************************************************************
  1781. *END
  1782.  
  1783. nkc_conin:     tst.b    prvvalid             ; previous character in buffer?
  1784.                beq.s    .getkey              ; no->
  1785.  
  1786.                clr.b    prvvalid             ; remove key code from buffer
  1787.                move     prvkey,d0            ; get key code
  1788.                rts                           ; bye
  1789.  
  1790.  
  1791. .getkey:       movem.l  d3-d7/a2-a6,-(sp)    ; save registers
  1792.                clr      d0                   ; don't check Alternate state
  1793.                bsr      nk_gci               ; get key code
  1794.                lea      nk_gci(pc),a0        ; ^function to execute
  1795.                bsr      nk_spec              ; special key handling
  1796.                movem.l  (sp)+,d3-d7/a2-a6    ; restore registers
  1797.                rts                           ; bye
  1798.  
  1799.  
  1800.  
  1801. *START
  1802. ****************************************************************************
  1803. *
  1804. *  nkc_cstat: return console character input status
  1805. *  # G
  1806. *
  1807. *  This function checks, if a key is in the key input buffer or not.
  1808. *
  1809. *  In:   -
  1810. *
  1811. *  Out:  D0.W           flag:
  1812. *                       0     no key in buffer
  1813. *                       -1    at least one key in buffer
  1814. *        CCR            set according content of D0.W
  1815. *
  1816. *  Reg:  D:01234567   A:01234567   CCR
  1817. *          W**.....     **......   =D0.W
  1818. *
  1819. ****************************************************************************
  1820. *END
  1821.  
  1822. nkc_cstat:     tst.b    prvvalid             ; previous character in buffer?
  1823.                sne.b    d0                   ; $ff = yes, $00 = no
  1824.                ext      d0                   ; as word
  1825.                bne.s    .exit                ; char available: exit
  1826.  
  1827.                move.l   a2,-(sp)             ; save register for Turbo C/Pure C
  1828.  
  1829.                move     #11,-(sp)            ; Cconis
  1830.                trap     #1                   ; Gemdos
  1831.                addq     #2,sp                ; clean stack
  1832.  
  1833.                move.l   (sp)+,a2             ; restore register
  1834.                tst      d0                   ; set CCR
  1835.  
  1836. .exit:         rts                           ; bye
  1837.  
  1838.  
  1839.  
  1840.                .if      NKCGEM=1
  1841.  
  1842. *START
  1843. ****************************************************************************
  1844. *
  1845. *  nkc_multi: NKCC multi event
  1846. *  # G U
  1847. *
  1848. *  nkc_multi() is a binding function to the AES multi event handler. The
  1849. *  only differences are the keyboard events and the shift key state: the key
  1850. *  codes are returned in normalized format (see nkc_tconv()), the shift key
  1851. *  state is compatible to the NKF?_... flags. For a detailed description of
  1852. *  the whole mass of parameters consult your AES manual or compiler handbook!
  1853. *
  1854. *  In:    4(SP).w       event mask (MU_...)
  1855. *         6(SP).w       MU_BUTTON: max # of clicks to wait for
  1856. *         8(SP).w       MU_BUTTON: mask of buttons to check
  1857. *        10(SP).w       MU_BUTTON: button states to wait for
  1858. *        12(SP).w       MU_M1: area enter/leave flag
  1859. *        14(SP).w       MU_M1: x position of area
  1860. *        16(SP).w       MU_M1: y position of area
  1861. *        18(SP).w       MU_M1: width of area
  1862. *        20(SP).w       MU_M1: height of area
  1863. *        22(SP).w       MU_M2: area enter/leave flag
  1864. *        24(SP).w       MU_M2: x position of area
  1865. *        26(SP).w       MU_M2: y position of area
  1866. *        28(SP).w       MU_M2: width of area
  1867. *        30(SP).w       MU_M2: height of area
  1868. *        32(SP).L       MU_MESAG: ^8 words of message buffer
  1869. *        36(SP).w       MU_TIMER: low word of time to wait
  1870. *        38(SP).w       MU_TIMER: high word of time to wait
  1871. *        40(SP).L       MU_BUTTON/M1/M2: ^word for mouse x
  1872. *        44(SP).L       MU_BUTTON/M1/M2: ^word for mouse y
  1873. *        48(SP).L       MU_BUTTON/M1/M2: ^word for button state
  1874. *        52(SP).L       MU_BUTTON/M1/M2: ^word for shift state
  1875. *        56(SP).L       MU_KEYBD: ^word for key code in normalized format
  1876. *        60(SP).L       MU_BUTTON: ^word for # of mouse clicks
  1877. *
  1878. *  Out:  D0.W           mask of occured events (MU_...)
  1879. *
  1880. *  Reg:  D:01234567   A:01234567   CCR
  1881. *          W**.....     **......    *
  1882. *
  1883. ****************************************************************************
  1884. *END
  1885.  
  1886. nkc_multi:     tst.b    prvvalid             ; previous character in buffer?
  1887.                beq.s    .mevent              ; no ->
  1888.  
  1889.                clr.b    prvvalid             ; remove key code from buffer
  1890.                move.l   56(sp),a0            ; ^buffer for key code
  1891.                move     prvkey,(a0)          ; return key code
  1892.                moveq.l  #MU_KEYBD,d0         ; a keyboard event occured
  1893.                rts                           ; bye
  1894.  
  1895. .mevent:       movem.l  d3-d7/a2-a6,-(sp)    ; save registers
  1896.  
  1897.  
  1898. *------------- transfer stack arguments to GEM parameter arrays
  1899.  
  1900.                lea      10*4+4(sp),a0        ; ^first parameter
  1901.                lea      nkc_intin,a1         ; ^integer in array
  1902.                movem.l  (a0)+,d1-d7          ; get the first 14 words
  1903.                movem.l  d1-d7,(a1)           ; place them in intin
  1904.                move.l   (a0)+,nkc_adrin      ; ^message buffer in addrin
  1905.                move.l   (a0),7*4(a1)         ; timer event lo and hi count
  1906.  
  1907.                bsr      nk_mctrl             ; setup control array
  1908.  
  1909.  
  1910. *------------- execute multi event
  1911.  
  1912.                bsr      nk_bestart           ; start handling for button event
  1913.                bsr      nk_msave             ; save multi event parameters
  1914.  
  1915. .wait:         cmp      #25,nkc_contrl       ; still evnt_multi() opcode?!?
  1916.                beq.s    .aes                 ; yes ->
  1917.  
  1918.                bsr      nk_mrestore          ; NO! AES corrupted it! restore
  1919.  
  1920. .aes:          lea      nkc_intin,a0         ; ^intin
  1921.                move     (a0),-(sp)           ; save event mask
  1922.                and      #~MU_XTIMER,(a0)     ; clear x-timer flag
  1923.                move     #200,d0              ; opcode for AES
  1924.                move.l   #aespb,d1            ; ^AES parameter block
  1925.                trap     #2                   ; call GEM
  1926.                move     (sp)+,nkc_intin      ; restore event mask
  1927.  
  1928.                move     nkc_intout,d0        ; mask of occured events
  1929.                and      #MU_KEYBD,d0         ; keyboard event?
  1930.                bne.s    .buthnd              ; yes ->
  1931.  
  1932.                move.l   kbdiorec,a0          ; no: get ^keyboard's I/O record
  1933.                move     IBUFHD(a0),iohead    ; reset NKCC's head pointer
  1934.  
  1935. .buthnd:       bsr      nk_beend             ; end handling of button event
  1936.                tst      nkc_intout           ; did any event occur?
  1937.                beq.s    .wait                ; no ->
  1938.  
  1939.  
  1940. *------------- return intout parameters via pointers
  1941.  
  1942.                movem.l  10*4+40(sp),a0-a5    ; get return pointers
  1943.                lea      nkc_intout,a6        ; ^intout array
  1944.                move     (a6)+,d0             ; mask of occured events
  1945.                move     (a6)+,(a0)           ; mouse x
  1946.                move     (a6)+,(a1)           ; mouse y
  1947.                move     (a6)+,(a2)           ; mouse button state
  1948.                move.b   1(a6),(a3)           ; shift key state (NKC flag
  1949.                                              ;  compatible!)
  1950.                clr.b    1(a3)                ; clear low byte of shift state
  1951.                move.l   a6,a3                ; ^shift state in intout
  1952.                move     4(a6),(a5)           ; # of mouse clicks
  1953.                move     2(a6),(a4)           ; key code
  1954.  
  1955. * You wonder why (a4) is written as last one and (a3) points to intout
  1956. * instead of the original return location? This is for the case that
  1957. * the caller isn't interested in one or some of the return values and
  1958. * let them point to ONE dummy variable.
  1959.  
  1960.  
  1961. *------------- check if keyboard event occured and convert key code, if so
  1962.  
  1963.                moveq.l  #MU_KEYBD,d1         ; the flag to test
  1964.                and      d0,d1                ; is it set?
  1965.                beq.s    .exit                ; no-> exit
  1966.  
  1967.                move     d0,-(sp)             ; save event mask
  1968.                move.l   a4,-(sp)             ; save ^key code
  1969.  
  1970.                move     (a4),d0              ; scan code + ASCII code
  1971.                moveq.l  #MU_BUTTON|MU_M1|MU_M2,d1  ; any of the events checked
  1972.                and      10*4+4+6(a7),d1      ; which return shift state?
  1973.                bne.s    .useiout             ; yes->
  1974.  
  1975.                move.l   pshift,a3            ; no: get shift state directly
  1976.                move.b   (a3),d1              ; get it
  1977.                and      #$f,d1               ; isolate valid bits
  1978.                bra.s    .conv
  1979.  
  1980. .useiout:      move     (a3),d1              ; get shift state from intout
  1981.  
  1982. .conv:         bsr      nk_bioscode          ; convert to BIOS format
  1983.                bsr      nk_real_shift        ; try to get original shift flags
  1984.                bsr      nkc_tconv            ; convert to normalized format
  1985.                lea      nk_mci(pc),a0        ; ^function to execute
  1986.                bsr      nk_spec              ; special key code handling
  1987.  
  1988.                move.l   (sp)+,a0             ; restore ^key code
  1989.                move     d0,(a0)              ; return key code
  1990.  
  1991.                move     (sp)+,d0             ; restore event mask
  1992.                move     d0,nkc_intout        ; and intout (changed by nk_spec)
  1993.  
  1994. .exit:         movem.l  (sp)+,d3-d7/a2-a6    ; restore registers
  1995.                rts                           ; bye
  1996.  
  1997.  
  1998.  
  1999.  
  2000. *START
  2001. ****************************************************************************
  2002. *
  2003. *  nkc_amulti: NKCC multi event called by Assembler  *** added by Gerd Knops
  2004. *  # G U
  2005. *
  2006. *  See description of nkc_multi()!
  2007. *
  2008. *  usage: instead of    move.l   #aespb,d1
  2009. *                       move  #$c8,d0
  2010. *                       trap  #2
  2011. *
  2012. *         do            jsr   nkc_amulti
  2013. *
  2014. *  In:   all parameters for evnt_multi in the AES parameter arrays
  2015. *
  2016. *  Out:  values in intout and message buffer
  2017. *
  2018. *  Reg:  D:01234567   A:01234567   CCR
  2019. *          ***.....     **......    *
  2020. *
  2021. ****************************************************************************
  2022. *END
  2023.  
  2024. nkc_amulti:    tst.b    prvvalid             ; previous character in buffer?
  2025.                beq.s    .mevent              ; no->
  2026.  
  2027.                clr.b    prvvalid             ; remove key code from buffer
  2028.                clr      nkc_intout+8         ; no SHIFT etc.
  2029.                move     prvkey,nkc_intout+10 ; return key code
  2030.                move     #MU_KEYBD,nkc_intout ; a keyboard event occured
  2031.                rts                           ; bye
  2032.  
  2033. .mevent:       movem.l  d3-d7/a2-a6,-(sp)    ; save registers
  2034.  
  2035.                move     nkc_intin,-(sp)      ; events to get
  2036.  
  2037.  
  2038. *------------- execute multi event
  2039.  
  2040.                bsr      nk_bestart           ; start handling for button event
  2041.                bsr      nk_msave             ; save multi event parameters
  2042.  
  2043. .wait:         cmp      #25,nkc_contrl       ; still evnt_multi() opcode?!?
  2044.                beq.s    .aes                 ; yes ->
  2045.  
  2046.                bsr      nk_mrestore          ; NO! AES corrupted it! restore
  2047.  
  2048. .aes:          lea      nkc_intin,a0         ; ^intin
  2049.                move     (a0),-(sp)           ; save event mask
  2050.                and      #~MU_XTIMER,(a0)     ; clear x-timer flag
  2051.                move     #200,d0              ; opcode for AES
  2052.                move.l   #aespb,d1            ; ^AES parameter block
  2053.                trap     #2                   ; call GEM
  2054.                move     (sp)+,nkc_intin      ; restore event mask
  2055.  
  2056.                move     nkc_intout,d0        ; mask of occured events
  2057.                and      #MU_KEYBD,d0         ; keyboard event?
  2058.                bne.s    .buthnd              ; yes ->
  2059.  
  2060.                move.l   kbdiorec,a0          ; no: get ^keyboard's I/O record
  2061.                move     IBUFHD(a0),iohead    ; reset NKCC's head pointer
  2062.  
  2063. .buthnd:       bsr      nk_beend             ; end handling of button event
  2064.                tst      nkc_intout           ; did any event occur?
  2065.                beq.s    .wait                ; no ->
  2066.  
  2067.                move     (sp)+,d2             ; events to get
  2068.  
  2069.  
  2070. *------------- check if keyboard event occured and convert key code, if so
  2071.  
  2072.                lea      nkc_intout+8,a3      ; ^shift key state
  2073.                move     (a3),d0              ; make in NKF?_... compatible
  2074.                move.b   d0,(a3)
  2075.                clr.b    1(a3)
  2076.  
  2077.                move     nkc_intout,d0        ; mask of received events
  2078.                moveq.l  #MU_KEYBD,d1         ; the flag to test
  2079.                and      d0,d1                ; is it set?
  2080.                beq.s    .exit                ; no-> exit
  2081.  
  2082.                move     d0,-(sp)             ; save event mask
  2083.  
  2084.                move     nkc_intout+10,d0     ; scan code + ASCII code
  2085.                moveq.l  #MU_BUTTON|MU_M1|MU_M2,d1  ; any of the events checked
  2086.                and      d2,d1                ; which return shift state?
  2087.                bne.s    .useiout             ; yes->
  2088.  
  2089.                move.l   pshift,a3            ; no: get shift state directly
  2090.                move.b   (a3),d1              ; get it
  2091.                and      #$f,d1               ; isolate valid bits
  2092.                bra.s    .conv
  2093.  
  2094. .useiout:      move     nkc_intout+8,d1      ; get shift state from intout
  2095.                lsr      #8,d1                ; in TOS format
  2096.  
  2097. .conv:         bsr      nk_bioscode          ; convert to BIOS format
  2098.                bsr      nk_real_shift        ; try to get original shift flags
  2099.                bsr.s    nkc_tconv            ; convert to normalized format
  2100.                lea      nk_mci(pc),a0        ; ^function to execute
  2101.                bsr      nk_spec              ; special key code handling
  2102.  
  2103.                move     d0,nkc_intout+10     ; save keycode
  2104.                move     (sp)+,d0             ; restore event mask
  2105.                move     d0,nkc_intout        ; and intout (changed by nk_spec)
  2106.  
  2107. .exit:         movem.l  (sp)+,d3-d7/a2-a6    ; restore registers
  2108.                rts                           ; bye
  2109.  
  2110.                .endif   ; .if NKCGEM=1
  2111.  
  2112.  
  2113.  
  2114. *START
  2115. ****************************************************************************
  2116. *
  2117. *  nkc_tconv: TOS key code converter
  2118. *  # G R
  2119. *
  2120. *  This is the most important function within NKCC: it takes a key code
  2121. *  returned by TOS and converts it to the sophisticated normalized format.
  2122. *
  2123. *  Note: the raw converter does no deadkey handling, ASCII input or
  2124. *        Control key emulation.
  2125. *
  2126. *  In:   D0.L           key code in TOS format:
  2127. *                                   0                    1
  2128. *                       bit 31:     ignored              ignored
  2129. *                       bit 30:     ignored              ignored
  2130. *                       bit 29:     ignored              ignored
  2131. *                       bit 28:     no CapsLock          CapsLock
  2132. *                       bit 27:     no Alternate         Alternate pressed
  2133. *                       bit 26:     no Control           Control pressed
  2134. *                       bit 25:     no left Shift key    left Shift pressed
  2135. *                       bit 24:     no right Shift key   right Shift pressed
  2136. *
  2137. *                       bits 23...16: scan code
  2138. *                       bits 15...08: ignored
  2139. *                       bits 07...00: ASCII code (or rubbish in most cases
  2140. *                          when Control or Alternate is pressed ...)
  2141. *
  2142. *  Out:  D0.W           normalized key code:
  2143. *                       bits 15...08: flags:
  2144. *                                   0                    1
  2145. *                       NKF?_FUNC   printable char       "function key"
  2146. *                       NKF?_RESVD  ignore it            ignore it
  2147. *                       NKF?_NUM    main keypad          numeric keypad
  2148. *                       NKF?_CAPS   no CapsLock          CapsLock
  2149. *                       NKF?_ALT    no Alternate         Alternate pressed
  2150. *                       NKF?_CTRL   no Control           Control pressed
  2151. *                       NKF?_LSH    no left Shift key    left Shift pressed
  2152. *                       NKF?_RSH    no right Shift key   right Shift pressed
  2153. *
  2154. *                       bits 07...00: key code
  2155. *                       function (NKF?_FUNC set):
  2156. *                          < 32: special key (NK_...)
  2157. *                          >=32: printable char + Control and/or Alternate
  2158. *                       no function (NKF?_FUNC not set):
  2159. *                          printable character (0...255!!!)
  2160. *
  2161. *        CCR            set according content of D0.W
  2162. *
  2163. *  Reg:  D:01234567   A:01234567   CCR
  2164. *          U**.....     **......   =D0.W
  2165. *
  2166. ****************************************************************************
  2167. *END
  2168. *
  2169. * Usage of the NKF?_RESVD flag:
  2170. *
  2171. * If the flag is set, the function nkc_cmp(), which evaluates the flag,
  2172. * has to check the state of the shift keys when comparing two key codes.
  2173. *
  2174. * Don't use the flag outside NKCC! Its content and meaning may change
  2175. * in future versions without notice!
  2176. *
  2177. ****************************************************************************
  2178.  
  2179. nkc_tconv:     movem.l  d3/d4,-(sp)          ; save registers
  2180.  
  2181.  
  2182. *------------- separate TOS key code
  2183.  
  2184.                move.l   d0,d1                ; TOS key code
  2185.                swap     d1                   ; .W = scan code and flags
  2186.                move     d1,d2                ; copy
  2187.                move     #$ff,d3              ; and-mask
  2188.                and      d3,d0                ; .B = ASCII code
  2189.                and      d3,d1                ; .B = scan code
  2190.                beq      .tos306              ; scancode=zero (key code created
  2191.                                              ;  by ASCII input of TOS 3.06)? ->
  2192.                and      #$1f00,d2            ; .W = key flags (in high byte)
  2193.  
  2194.  
  2195. *------------- decide which translation table to use
  2196.  
  2197.                move     d2,d3                ; key flags
  2198.                and      #NKFf_SHIFT,d3       ; isolate bits for shift keys
  2199.                beq.s    .ktab1               ; shift key pressed? no->
  2200.  
  2201.                move.l   pkey_shift,a0        ; yes: use shift table
  2202.                bra.s    .ktab3               ; ->
  2203.  
  2204. .ktab1:        btst.l   #NKFb_CAPS,d2        ; CapsLock?
  2205.                beq.s    .ktab2               ; no->
  2206.  
  2207.                move.l   pkey_caps,a0         ; yes: use CapsLock table
  2208.                bra.s    .ktab3               ; ->
  2209.  
  2210. .ktab2:        move.l   pkey_unshift,a0      ; use unshifted table
  2211.  
  2212.  
  2213. *------------- check if Alternate + number: they have simulated scan codes
  2214.  
  2215. .ktab3:        cmp.b    #$78,d1              ; scan code of Alt + number?
  2216.                blo.s    .scan1               ; no->
  2217.  
  2218.                sub.b    #$76,d1              ; yes: calculate REAL scan code
  2219.                move.b   (a0,d1),d0           ; fetch ASCII code
  2220.                or       #NKFf_ALT,d2         ; set Alternate flag
  2221.                bra      .cat_codes           ; -> add flag byte and exit
  2222.  
  2223.  
  2224. *------------- check if exception scan code from cursor keypad
  2225.  
  2226. .scan1:        lea      xscantab,a1          ; ^exception scan code table
  2227.  
  2228. .search_scan:  move     (a1)+,d3             ; NKC and scan code
  2229.                bmi.s    .tabend              ; <0? end of table reached ->
  2230.  
  2231.                cmp.b    d1,d3                ; scan code found?
  2232.                bne.s    .search_scan         ; no: continue search ->
  2233.  
  2234.                lsr      #8,d3                ; .B = NKC
  2235.                moveq.l  #0,d0                ; mark: key code found
  2236.                bra.s    .scan2               ; ->
  2237.  
  2238. .tabend:       moveq.l  #0,d3                ; no NKC found yet
  2239.  
  2240.  
  2241. *------------- check if rubbish ASCII code and erase it, if so
  2242.  
  2243. .scan2:        move.b   (a0,d1),d4           ; ASCII code from translation table
  2244.                cmp.b    #32,d0               ; ASCII returned by TOS < 32?
  2245.                bhs.s    .scan3               ; no -> can't be rubbish
  2246.  
  2247.                cmp.b    d4,d0                ; yes: compare with table entry
  2248.                beq.s    .scan3               ; equal: that's ok ->
  2249.  
  2250.                moveq.l  #0,d0                ; not equal: rubbish! clear it
  2251.  
  2252.  
  2253. *------------- check if ASCII code could only be produced via Alternate key
  2254. *              combination
  2255.  
  2256. .scan3:        tst.b    d0                   ; ASCII code valid?
  2257.                beq.s    .scan4               ; no ->
  2258.  
  2259.                cmp.b    d4,d0                ; compare with table entry
  2260.                beq.s    .scan4               ; equal: normal key ->
  2261.  
  2262.                and      #~NKFf_ALT,d2        ; no: clear Alternate flag
  2263.  
  2264.  
  2265. *------------- check if ASCII code found yet, and set it, if not
  2266.  
  2267. .scan4:        tst.b    d0                   ; found?
  2268.                bne.s    .scan5               ; yes ->
  2269.  
  2270.                move.b   d3,d0                ; no: use code from exception table
  2271.                bne.s    .scan5               ; now valid? yes ->
  2272.  
  2273.                move.b   d4,d0                ; no: use code from transl. table
  2274.  
  2275.  
  2276. *------------- check special case: delete key
  2277.  
  2278. .scan5:        cmp.b    #127,d0              ; ASCII code of Delete?
  2279.                bne.s    .scan6               ; no ->
  2280.  
  2281.                move.b   #NK_DEL,d0           ; yes: set according NKC
  2282.  
  2283.  
  2284. *------------- check if key is on numeric keypad (via scan code)
  2285.  
  2286. .scan6:        cmp.b    #$4a,d1              ; numeric pad scan code range?
  2287.                beq.s    .numeric             ; yes ->
  2288.  
  2289.                cmp.b    #$4e,d1
  2290.                beq.s    .numeric             ; yes ->
  2291.  
  2292.                cmp.b    #$63,d1
  2293.                blo.s    .scan7               ; no ->
  2294.  
  2295.                cmp.b    #$72,d1
  2296.                bhi.s    .scan7               ; no ->
  2297.  
  2298. .numeric:      or       #NKFf_NUM,d2         ; yes: set numeric bit
  2299.  
  2300.  
  2301. *------------- check if "function key" and set bit accordingly
  2302.  
  2303. .scan7:        cmp.b    #32,d0               ; ASCII code less than 32?
  2304.                bhs.s    .scan8               ; no ->
  2305.  
  2306.                or       #NKFf_FUNC,d2        ; yes: set function bit
  2307.  
  2308.  
  2309. *------------- check special case: Return or Enter key
  2310.  
  2311.                cmp.b    #13,d0               ; Return or Enter key?
  2312.                bne.s    .scan8               ; no ->
  2313.  
  2314.                btst.l   #NKFb_NUM,d2         ; yes: from the numeric pad?
  2315.                beq.s    .scan8               ; no -> it's Return, keep code
  2316.  
  2317.                moveq.l  #NK_ENTER,d0         ; yes: it's Enter; new code
  2318.  
  2319.  
  2320. *------------- check if function key (F1-F10) via scan code
  2321.  
  2322. .scan8:        cmp.b    #$54,d1              ; shift + function key?
  2323.                blo.s    .scan9               ; no ->
  2324.  
  2325.                cmp.b    #$5d,d1
  2326.                bhi.s    .scan9               ; no ->
  2327.  
  2328.                sub.b    #$54-$3b,d1          ; yes: scan code for unshifted key
  2329.                move     d2,d3                ; shift flags
  2330.                and      #NKFf_SHIFT,d3       ; any shift key flag set?
  2331.                bne.s    .scan9               ; yes ->
  2332.                or       #NKFf_SHIFT,d2       ; no: set both flags
  2333.  
  2334. .scan9:        cmp.b    #$3b,d1              ; (unshifted) function key?
  2335.                blo.s    .cat_codes           ; no ->
  2336.  
  2337.                cmp.b    #$44,d1
  2338.                bhi.s    .cat_codes           ; no ->
  2339.  
  2340.                move.b   d1,d0                ; yes: calc NKC
  2341.                sub.b    #$2b,d0
  2342.  
  2343.  
  2344. *------------- final flag handling; mix key code (low byte) and flag byte
  2345.  
  2346. .cat_codes:    move.l   pkey_shift,a0        ; ^shifted table
  2347.                move.b   (a0,d1),d3           ; get shifted ASCII code
  2348.                or       d2,d0                ; mix flags with key code
  2349.                bmi.s    .scan10              ; result is "function key"? ->
  2350.  
  2351.                and      #NKFf_CTRL+NKFf_ALT,d2  ; Control or Alternate pressed?
  2352.                bne.s    .scan11              ; yes ->
  2353.  
  2354. .scan10:       move.l   pkey_unshift,a0      ; ^unshifted table
  2355.                cmp.b    (a0,d1),d3           ; shifted ASCII = unshifted ASCII?
  2356.                beq.s    .scan12              ; yes ->
  2357.  
  2358.                bra.s    .exit                ; no ->
  2359.  
  2360. .scan11:       or       #NKFf_FUNC,d0        ; Alt/Ctrl + char: set function bit
  2361.                move.l   pkey_caps,a0         ; ^CapsLock table
  2362.                cmp.b    (a0,d1),d3           ; shifted ASCII = CapsLocked ASCII?
  2363.                bne.s    .exit                ; no ->
  2364.  
  2365.                move.b   d3,d0                ; yes: use shifted ASCII code
  2366.  
  2367. .scan12:       or       #NKFf_RESVD,d0       ; yes: nkc_cmp() has to check
  2368.                                              ;  the Shift keys
  2369.  
  2370. *------------- restore registers and exit
  2371.  
  2372. .exit:         tst      d0                   ; set CCR
  2373.                movem.l  (sp)+,d3/d4          ; restore registers
  2374.                rts                           ; bye
  2375.  
  2376.  
  2377. *------------- special handling for key codes created by TOS' 3.06 ASCII input
  2378.  
  2379. .tos306:       and      #NKFf_CAPS,d2        ; isolate CapsLock flag
  2380.                or       d2,d0                ; merge with ASCII code
  2381.                movem.l  (sp)+,d3/d4          ; restore registers
  2382.                rts                           ; bye
  2383.  
  2384.  
  2385.  
  2386.  
  2387. *START
  2388. ****************************************************************************
  2389. *
  2390. *  nkc_gconv: GEM key code converter
  2391. *  # G R
  2392. *
  2393. *  Why a second key code converter, you ask? Well, in some cases it might
  2394. *  happen that the key status byte of the original key code (with states
  2395. *  of both Shift keys, Control, Alternate and CapsLock) is lost. Then
  2396. *  this converter function must be called, which uses another algorithm
  2397. *  to construct the normalized key code.
  2398. *
  2399. *  Notes:
  2400. *  -  the raw converter does no deadkey handling, ASCII input or Control
  2401. *     key emulation.
  2402. *  -  NKCC does not use this function at all for its own purposes!
  2403. *  -  some key combinations cannot be distinguished without the flag byte!
  2404. *     For example, "Alternate A" and "Shift Alternate A" produce the same
  2405. *     result. Whenever possible, use nkc_tconv()!
  2406. *
  2407. *  In:   D0.W           key code in GEM format:
  2408. *                       bits 15...08: scan code
  2409. *                       bits 07...00: ASCII code
  2410. *
  2411. *  Out:  D0.W           normalized key code (see nkc_tconv() for details)
  2412. *        CCR            set according content of D0.W
  2413. *
  2414. *  Reg:  D:01234567   A:01234567   CCR
  2415. *          U**.....     **......   =D0.W
  2416. *
  2417. ****************************************************************************
  2418. *END
  2419.  
  2420. nkc_gconv:     movem.l  d4-d7,-(sp)          ; save registers
  2421.  
  2422.  
  2423. *------------- find out "real" scan code and convert to TOS key code format
  2424.  
  2425.                move     d0,d1                ; copy key code
  2426.                lsr      #8,d1                ; scan code in d1.w
  2427.                swap     d0                   ; move key code to high word
  2428.                move.l   pshift,a0            ; ^key state flags
  2429.                move.b   (a0),d0              ; get 'em
  2430.                and      #NKFf_CAPS>>8,d0     ; isolate CapsLock flag
  2431.                lea      scan_trans,a0        ; ^scan code translation table
  2432.  
  2433. .trans:        move.l   (a0)+,d2             ; get next entry
  2434.                beq.s    .endtrans            ; end of table? ->
  2435.  
  2436.                cmp.b    d1,d2                ; scan code found?
  2437.                bne.s    .trans               ; no ->
  2438.  
  2439.                lsr      #8,d2                ; "real" scan code
  2440.                move.b   d2,d1                ; use it
  2441.                swap     d2                   ; flags to set
  2442.                or       d2,d0                ; set them
  2443.  
  2444. .endtrans:     swap     d0                   ; move flags up and key code down
  2445.                moveq.l  #0,d7                ; clear for word operation
  2446.                move.b   d0,d7                ; copy ASCII code
  2447.                lsl.l    #8,d0                ; shift flags and scan code up
  2448.                move     d7,d0                ; restore ASCII code
  2449.  
  2450.  
  2451. *------------- try to restore some of the key flags (shift/control/alternate)
  2452.  
  2453.                move.l   pkey_unshift,a0      ; ^unshifted key table
  2454.                move.b   (a0,d1),d4           ; get unshifted code
  2455.                move.l   pkey_shift,a0        ; ^shifted key table
  2456.                move.b   (a0,d1),d5           ; get shifted code
  2457.                move.l   pkey_caps,a0         ; ^CapsLock key table
  2458.                move.b   (a0,d1),d6           ; get CapsLock code
  2459.  
  2460.                bsr      nk_ascmatch          ; try to find ASCII code
  2461.                beq.s    .conv                ; found ->
  2462.  
  2463.                move.b   #$1f,d2              ; maybe modified by Control key...
  2464.                and.b    d2,d4                ; change ASCII code accordingly
  2465.                and.b    d2,d5
  2466.                and.b    d2,d6
  2467.                bsr      nk_ascmatch          ; and try again
  2468.                bne.s    .notfnd              ; no match ->
  2469.  
  2470. .setctrl:      or.l     #(NKFf_FUNC|NKFf_CTRL)<<16,d0    ; Control was pressed
  2471.                bra.s    .conv                ; ->
  2472.  
  2473. .notfnd:       move.l   pkey_unshift,a0      ; not found: restore all three
  2474.                move.b   (a0,d1),d2           ;  ASCII codes
  2475.                move.l   pkey_shift,a0
  2476.                move.b   (a0,d1),d5
  2477.                move.l   pkey_caps,a0
  2478.                move.b   (a0,d1),d6
  2479.                bsr.s    .translate           ; translate unshifted code
  2480.  
  2481.                move.b   d2,d4                ; use translated code
  2482.                move.b   d5,d2                ; translate shifted code
  2483.                bsr.s    .translate
  2484.  
  2485.                move.b   d2,d5                ; use translated code
  2486.                move.b   d6,d2                ; translate shifted code
  2487.                bsr.s    .translate
  2488.  
  2489.                move.b   d2,d6                ; use translated code
  2490.                bsr      nk_ascmatch          ; last try to locate ASCII code
  2491.                beq.s    .setctrl             ; found ->
  2492.  
  2493.                tst.b    d0                   ; not found: ASCII code is 0?
  2494.                bne.s    .conv                ; no ->
  2495.  
  2496.                btst.l   #NKFb_CTRL+16,d0     ; Control key flag already set?
  2497.                bne.s    .conv                ; yes ->
  2498.  
  2499.                                              ; no: must be Alternate
  2500.                or.l     #(NKFf_FUNC|NKFf_ALT)<<16,d0
  2501.  
  2502.  
  2503. *------------- do conversion to normalized format
  2504.  
  2505. .conv:         bsr      nkc_tconv            ; do TOS key code conversion
  2506.  
  2507.                movem.l  (sp)+,d4-d7          ; restore registers
  2508.                tst      d0                   ; set CCR
  2509.                rts                           ; bye
  2510.  
  2511.  
  2512. *  This small sub function changes the ASCII code in D2.B due to the
  2513. *  ASCII code translation table asc_trans. The result is returned in D2.B,
  2514. *  registers D7 and A0 are corrupted.
  2515.  
  2516. .translate:    lea      asc_trans,a0         ; ^translation table
  2517.  
  2518. .transloop:    move     (a0)+,d7             ; get both codes
  2519.                beq.s    .ret                 ; end of table? ->
  2520.  
  2521.                cmp.b    d2,d7                ; found?
  2522.                bne.s    .transloop           ; no ->
  2523.  
  2524.                lsr      #8,d7                ; yes: get translated code
  2525.                move.b   d7,d2                ; and use it
  2526.  
  2527. .ret:          rts                           ; bye
  2528.  
  2529.  
  2530.  
  2531. *START
  2532. ****************************************************************************
  2533. *
  2534. *  nkc_n2tos: convert normalized key codes back to TOS format
  2535. *  # G R
  2536. *
  2537. *  In some cases you might have to have key codes in the original TOS format
  2538. *  again, as returned by the GEMDOS functions Cconin(), Crawcin() or the BIOS
  2539. *  function Bconin(). Use nkc_n2tos() to convert them. For a detailed
  2540. *  description of the returned format consult the header of the function
  2541. *  nkc_tconv().
  2542. *
  2543. *  In:   D0.W           key code in normalized format
  2544. *
  2545. *  Out:  D0.L           key code in TOS format:
  2546. *                       bits 24...31: shift key flags
  2547. *                       bits 23...16: scan code
  2548. *                       bits 08...15: reserved (0)
  2549. *                       bits 00...07: ASCII code
  2550. *        CCR            set according content of D0.L
  2551. *
  2552. *  Reg:  D:01234567   A:01234567   CCR
  2553. *          U**.....     **......   =D0.L
  2554. *
  2555. ****************************************************************************
  2556. *END
  2557.  
  2558. *------------- select system key table to use
  2559.  
  2560. nkc_n2tos:     move     d0,d1                ; normalized key code
  2561.                and      #NKFf_SHIFT,d1       ; isolate bits for shift keys
  2562.                beq.s    .ktab1               ; shift key pressed? no->
  2563.  
  2564.                lea      n_to_scan_s,a1       ; ^default translation table
  2565.                move.l   pkey_shift,a0        ; yes: use shift table
  2566.                bra.s    .ktab3               ; ->
  2567.  
  2568. .ktab1:        lea      n_to_scan_u,a1       ; ^unshifted translation table
  2569.                btst.l   #NKFb_CAPS,d0        ; CapsLock?
  2570.                beq.s    .ktab2               ; no->
  2571.  
  2572.                move.l   pkey_caps,a0         ; yes: use CapsLock table
  2573.                bra.s    .ktab3               ; ->
  2574.  
  2575. .ktab2:        move.l   pkey_unshift,a0      ; use unshifted table
  2576.  
  2577.  
  2578. *------------- handling for ASCII codes >= 32
  2579.  
  2580. .ktab3:        cmp.b    #32,d0               ; ASCII code < 32?
  2581.                blo.s    .lowascii            ; yes ->
  2582.  
  2583.                bsr      nk_findscan          ; find scan code
  2584.                bne.s    .found               ; found ->
  2585.  
  2586.                btst.l   #NKFb_FUNC,d0        ; function flag set?
  2587.                beq.s    .notfound            ; no ->
  2588.  
  2589.                move.l   a0,d1                ; save a0
  2590.                lea      tolower,a0           ; ^upper->lower case table
  2591.                moveq.l  #0,d2                ; clear for word operation
  2592.                move.b   d0,d2                ; ASCII code
  2593.                move.b   (a0,d2),d0           ; get lowercased ASCII code
  2594.                move.l   d1,a0                ; restore a0
  2595.                bsr      nk_findscan          ; try to find scan code again
  2596.                bne.s    .found               ; found ->
  2597.  
  2598.  
  2599. *------------- unknown source: treat key code as it was entered using the
  2600. *              TOS 3.06 direct ASCII input
  2601.  
  2602. .notfound:     moveq.l  #0,d1                ; not found: clear for word op.
  2603.                move.b   d0,d1                ; unchanged ASCII code
  2604.                and      #$1f00,d0            ; keep shift flags only
  2605.                swap     d0                   ; -> high word (scan code = 0)
  2606.                move     d1,d0                ; low word: ASCII code
  2607.                bra      .exit                ; ->
  2608.  
  2609.  
  2610. *------------- handling for ASCII codes < 32
  2611.  
  2612. .lowascii:     btst.l   #NKFb_FUNC,d0        ; function key?
  2613.                bne.s    .func                ; yes ->
  2614.  
  2615.                and      #$10ff,d0            ; clear all flags except CapsLock
  2616.                bra.s    .notfound            ; ->
  2617.  
  2618. .func:         moveq.l  #0,d1                ; clear for word operation
  2619.                move.b   d0,d1                ; ASCII code (0...$1f)
  2620.                move     d1,d2                ; copy
  2621.                move.b   (a1,d1),d1           ; get scan code
  2622.                bne.s    .getascii            ; valid? ->
  2623.  
  2624.                moveq    #0,d0                ; invalid key code!! return 0
  2625.                bra      .exit                ; ->
  2626.  
  2627. .getascii:     lea      n_to_scan_u,a1       ; ^unshifted translation table
  2628.                move.b   (a1,d2),d2           ; get scan code from unshifted tab.
  2629.                move.b   (a0,d2),d0           ; get ASCII from system's table
  2630.  
  2631.  
  2632. * register contents:
  2633. *
  2634. * d0.b         ASCII code
  2635. * d1.b         scan code
  2636. * d0.hb        NKCC flags
  2637. *
  2638.  
  2639. .found:        move     d0,d2                ; flags and ASCII code
  2640.                and      #$1f00,d0            ; isolate shift flags
  2641.                move.b   d1,d0                ; merge with scan code
  2642.                swap     d0                   ; -> high byte
  2643.                clr      d0                   ; erase low word
  2644.                move.b   d2,d0                ; restore ASCII code
  2645.  
  2646.  
  2647. *------------- handling for Control key flag
  2648.  
  2649.                btst.l   #NKFb_CTRL,d2        ; control key flag set?
  2650.                beq.s    .alternate           ; no ->
  2651.  
  2652.                cmp.b    #$4b,d1              ; scan code = "cursor left"?
  2653.                bne.s    .scanchk2            ; no ->
  2654.  
  2655.                add.l    #$280000,d0          ; change scan code to $73
  2656.                clr.b    d0                   ; erase ASCII code
  2657.                bra.s    .exit                ; ->
  2658.  
  2659. .scanchk2:     cmp.b    #$4d,d1              ; scan code = "cursor right"?
  2660.                bne.s    .scanchk3            ; no ->
  2661.  
  2662.                add.l    #$270000,d0          ; change scan code to $74
  2663.                clr.b    d0                   ; erase ASCII code
  2664.                bra.s    .exit                ; ->
  2665.  
  2666. .scanchk3:     cmp.b    #$47,d1              ; scan code = "ClrHome"?
  2667.                bne.s    .ascchk              ; no ->
  2668.  
  2669.                add.l    #$300000,d0          ; change scan code to $77
  2670. ; keep ASCII code in this case! What a mess...
  2671.                bra.s    .exit                ; ->
  2672.  
  2673. .ascchk:       lea      asc_trans,a0         ; ^ASCII translation table
  2674.  
  2675. .ascloop:      move     (a0)+,d1             ; get next entry
  2676.                beq.s    .noctrlasc           ; end of table ->
  2677.  
  2678.                cmp.b    d0,d1                ; ASCII code found?
  2679.                bne.s    .ascloop             ; no -> continue search
  2680.  
  2681.                lsr      #8,d1                ; yes: get translated code
  2682.                move.b   d1,d0                ; use it
  2683.                bra.s    .exit                ; ->
  2684.  
  2685. .noctrlasc:    and.b    #$1f,d0              ; mask off upper 3 bits
  2686.                bra.s    .exit                ; ->
  2687.  
  2688.  
  2689. *------------- handling for Alternate key flag
  2690.  
  2691. .alternate:    btst.l   #NKFb_ALT,d2         ; alternate key flag set?
  2692.                beq.s    .exit                ; no ->
  2693.  
  2694.                cmp.b    #2,d1                ; top row on main keyboard?
  2695.                blo.s    .alphachk            ; no ->
  2696.  
  2697.                cmp.b    #$d,d1
  2698.                bhi.s    .alphachk            ; no ->
  2699.  
  2700.                add.l    #$760000,d0          ; yes: change scan code
  2701.                clr.b    d0                   ; and erase ASCII code
  2702.                bra.s    .exit                ; ->
  2703.  
  2704. .alphachk:     cmp.b    #'A',d0              ; alpha-characters?
  2705.                blo.s    .exit                ; no ->
  2706.  
  2707.                cmp.b    #'z',d0
  2708.                bhi.s    .exit                ; no ->
  2709.  
  2710.                cmp.b    #'Z',d0
  2711.                bls.s    .ascii0              ; yes ->
  2712.  
  2713.                cmp.b    #'a',d0
  2714.                blo.s    .exit                ; no ->
  2715.  
  2716. .ascii0:       clr.b    d0                   ; alpha-character: clear ASCII code
  2717.  
  2718. .exit:         rts                           ; bye
  2719.  
  2720.  
  2721.  
  2722. *START
  2723. ****************************************************************************
  2724. *
  2725. *  nkc_n2gem: convert normalized key codes back to GEM format
  2726. *  # G R
  2727. *
  2728. *  Similar to nkc_n2tos(), this function converts normalized key codes back
  2729. *  to the operating system's format. The result is a key code as returned
  2730. *  by the AES functions evnt_keybd() respectively evnt_multi().
  2731. *
  2732. *  In:   D0.W           key code in normalized format
  2733. *
  2734. *  Out:  D0.W           key code in GEM format:
  2735. *                       bits 08...15: scan code
  2736. *                       bits 00...07: ASCII code
  2737. *        CCR            set according content of D0.W
  2738. *
  2739. *  Reg:  D:01234567   A:01234567   CCR
  2740. *          U**.....     **......   =D0.W
  2741. *
  2742. ****************************************************************************
  2743. *END
  2744.  
  2745. nkc_n2gem:     bsr      nkc_n2tos            ; convert
  2746.                moveq.l  #0,d1                ; clear for word operation
  2747.                move.b   d0,d1                ; ASCII code
  2748.                ror.l    #8,d0                ; scan code now in high byte
  2749.                move.b   d1,d0                ; put ASCII into low byte
  2750.                tst      d0                   ; set CCR
  2751.                rts                           ; bye
  2752.  
  2753.  
  2754.  
  2755. *START
  2756. ****************************************************************************
  2757. *
  2758. *  nkc_kstate: return state of Shift/Control/Alternate/CapsLock in
  2759. *              normalized format
  2760. *  # G R
  2761. *
  2762. *  This is a very *FAST* function which returns the state of the Shift/
  2763. *  Control/Alternate and CapsLock keys in normalized format.
  2764. *
  2765. *  In:   -
  2766. *
  2767. *  Out:  D0.W           normalized key flags:
  2768. *                                   0                    1
  2769. *                       NKF?_CAPS   no CapsLock          CapsLock
  2770. *                       NKF?_ALT    no Alternate         Alternate pressed
  2771. *                       NKF?_CTRL   no Control           Control pressed
  2772. *                       NKF?_LSH    no left Shift key    left Shift pressed
  2773. *                       NKF?_RSH    no right Shift key   right Shift pressed
  2774. *
  2775. *        CCR            set according content of D0.W
  2776. *
  2777. *  Reg:  D:01234567   A:01234567   CCR
  2778. *          w**.....     **......   =D0.W
  2779. *
  2780. ****************************************************************************
  2781. *END
  2782.  
  2783. nkc_kstate:    move.l   pshift,a0            ; ^shift state variable
  2784.                move.b   (a0),d0              ; get its contents
  2785.                and      #$1f,d0              ; isolate valid bits
  2786.                lsl      #8,d0                ; make it NKC compatible
  2787.                rts                           ; bye
  2788.  
  2789.  
  2790.  
  2791. *START
  2792. ****************************************************************************
  2793. *
  2794. *  nkc_timer: return current value of 200 Hz system clock
  2795. *  # G R
  2796. *
  2797. *  This is a very *FAST* function which returns the content of the 200 Hz
  2798. *  system clock.
  2799. *
  2800. *  In:   -
  2801. *
  2802. *  Out:  D0.L           current 200 HZ system clock value
  2803. *
  2804. *  Reg:  D:01234567   A:01234567   CCR
  2805. *          w**.....     **......    *
  2806. *
  2807. ****************************************************************************
  2808. *END
  2809.  
  2810. nkc_timer:     move.l   sysclock,d0          ; just get value
  2811.                rts                           ; bye bye
  2812.  
  2813.  
  2814.  
  2815. *START
  2816. ****************************************************************************
  2817. *
  2818. *  nkc_cmp: compare two key codes
  2819. *  # G R
  2820. *
  2821. *  nkc_cmp() compares key codes. What for, you ask? A simple "if key_code1
  2822. *  = key_code2" would also do it? No! This function follows some specific
  2823. *  rules, which improve the flexibility of key code comparism.
  2824. *
  2825. *  One of the key codes passed to nkc_cmp() is called the "reference key
  2826. *  code". The other is the "test key code", which is got from nkc_conin()
  2827. *  or nkc_multi(). Some flags of the reference code are treated a special
  2828. *  way:
  2829. *
  2830. *  NKF?_IGNUM (same as NKF?_RESVD)
  2831. *     if set, the numeric keypad flag doesn't matter
  2832. *
  2833. *  NKF?_CAPS (CapsLock)
  2834. *     if set, the case of the ASCII code doesn't matter
  2835. *
  2836. *  NKFf_SHIFT (both Shift key flags)
  2837. *     if BOTH shift flags are set, the combination of shift key flags in
  2838. *     the test key code doesn't matter: only one shift flag has to be set,
  2839. *     no matter which one.
  2840. *
  2841. *  In:   D0.W           reference key code
  2842. *        D1.W           key code to test
  2843. *
  2844. *  Out:  D0.W           flag: 1 = key codes match
  2845. *                             0 = key codes don't match
  2846. *        CCR            set according content of D0.W
  2847. *
  2848. *  Reg:  D:01234567   A:01234567   CCR
  2849. *          u**.....     **......   =D0.W
  2850. *
  2851. ****************************************************************************
  2852. *END
  2853.  
  2854. nkc_cmp:       movem.l  d3-d4,-(sp)          ; save registers
  2855.                move     d0,d2                ; reference key code
  2856.                eor      d1,d2                ; XORed with test key code
  2857.                beq      .match               ; identical: key codes match
  2858.  
  2859.                bmi.s    .nomatch             ; func flag differs -> don't match
  2860.  
  2861.                tst      d0                   ; "function" key?
  2862.                bmi.s    .rfunc               ; yes ->
  2863.  
  2864.  
  2865. *------------- printable character
  2866.  
  2867.                btst.l   #NKFb_IGNUM,d0       ; ignore numeric keypad flag?
  2868.                bne.s    .chkn1               ; yes ->
  2869.  
  2870.                btst.l   #NKFb_NUM,d2         ; numeric key flags equal?
  2871.                bne.s    .nomatch             ; no ->
  2872.  
  2873. .chkn1:        lea      toupper,a0           ; ^upper case conversion table
  2874.                moveq.l  #0,d3                ; clear for word operation
  2875.                move.b   d0,d3                ; ASCII code of ref key code
  2876.                move.b   (a0,d3),d4           ; get CapsLocked reference key code
  2877.  
  2878.                cmp.b    d0,d1                ; ASCII code equal?
  2879.                beq.s    .stest               ; yes ->
  2880.  
  2881.                btst.l   #NKFb_CAPS,d0        ; no: ignore case?
  2882.                beq.s    .nomatch             ; no -> codes don't match
  2883.  
  2884.                move.b   d1,d3                ; ASCII of test key code
  2885.                cmp.b    (a0,d3),d4           ; CapsLocked comparism
  2886.                beq.s    .match               ; equal ->
  2887.  
  2888.                bra.s    .nomatch             ; not equal ->
  2889.  
  2890. .stest:        btst.l   #NKFb_RESVD,d1       ; check Shift keys?
  2891.                beq.s    .match               ; no ->
  2892.  
  2893. .stest2:       move     #NKFf_SHIFT,d4       ; Shift key flags
  2894.                move     d2,d3                ; XORed key codes
  2895.                and      d4,d3                ; shift flags equal?
  2896.                beq.s    .match               ; yes ->
  2897.  
  2898.                move     d0,d3                ; reference key code
  2899.                and      d4,d3                ; isolate Shift flags
  2900.                cmp      d3,d4                ; both set?
  2901.                bne.s    .nomatch             ; no -> codes don't match
  2902.  
  2903.                move     d1,d3                ; check if any pressed in test code
  2904.                and      d4,d3
  2905.                bne.s    .match               ; yes ->
  2906.  
  2907.                bra.s    .nomatch             ; no ->
  2908.  
  2909.  
  2910. *------------- "function key"
  2911.  
  2912. .rfunc:        move     d2,d3                ; XORed key codes
  2913.                and      #NKFf_ALT|NKFf_CTRL,d3  ; check Alternate and Control
  2914.                bne.s    .nomatch             ; different -> codes don't match
  2915.  
  2916.                cmp.b    #32,d0               ; special key or character?
  2917.                bhs.s    .rchar               ; character->
  2918.  
  2919.                cmp.b    d0,d1                ; special key codes equal?
  2920.                beq.s    .stest2              ; yes ->
  2921.  
  2922.                bra.s    .nomatch             ; no ->
  2923.  
  2924. .rchar:        btst.l   #NKFb_IGNUM,d0       ; ignore numeric keypad flag?
  2925.                bne.s    .chkn2               ; yes ->
  2926.  
  2927.                btst.l   #NKFb_NUM,d2         ; numeric key flags equal?
  2928.                bne.s    .nomatch             ; no ->
  2929.  
  2930. .chkn2:        cmp.b    d0,d1                ; ASCII codes equal?
  2931.                beq.s    .stest               ; yes ->
  2932.  
  2933. .nomatch:      movem.l  (sp)+,d3-d4          ; restore registers
  2934.                moveq.l  #0,d0                ; codes don't match
  2935.                rts                           ; bye
  2936.  
  2937. .match:        movem.l  (sp)+,d3-d4          ; restore registers
  2938.                moveq.l  #1,d0                ; codes match
  2939.                rts                           ; bye
  2940.  
  2941.  
  2942.  
  2943. *START
  2944. ****************************************************************************
  2945. *
  2946. *  nkc_vlink: link function to XBRA vector list
  2947. *  # G U
  2948. *
  2949. *  This function can be used to change system vectors and let them point
  2950. *  to own functions, using a standard method. The vector, which should be
  2951. *  changed, is described by the contents of D0.L and D1.W. It can be
  2952. *  either a standard vector number, e.g. 2 for the bus error exception
  2953. *  vector, or the absolute address of the vector, e.g. $502 for the screen
  2954. *  dump vector. The function to install must have the following header:
  2955. *
  2956. *  .dc.b    "XBRA"         magic longword
  2957. *  .dc.b    "myID"         four ASCII character ID of the function
  2958. *                          (NKCC uses "NKCC", for example)
  2959. *  .dc.l    0              buffer for the old vector content
  2960. *  function: ...           start of the function code
  2961. *
  2962. *  The function should end with:
  2963. *
  2964. *  move.l   function-4(pc),-(sp)
  2965. *  rts
  2966. *
  2967. *
  2968. *  Note: in NKXM_ADR mode, this function automatically switches (temporary)
  2969. *        to Supervisor mode to prevent bus errors
  2970. *
  2971. *
  2972. *  In:   D0.L           vector descriptor
  2973. *        D1.W           mode:
  2974. *                       NKXM_NUM = D0.L contains a vector number
  2975. *                       NKXM_ADR = D0.L contains a vector address
  2976. *        A0.L           ^function to install (NOT ^XBRA header!)
  2977. *
  2978. *  Out:  -4(A0.L).L     old content of vector
  2979. *
  2980. *  Reg:  D:01234567   A:01234567   CCR
  2981. *          ***.....     **......    *
  2982. *
  2983. ****************************************************************************
  2984. *END
  2985.  
  2986.  
  2987. nkc_vlink:     tst      d1                   ; which mode?
  2988.                bne.s    .adr                 ; address ->
  2989.  
  2990.  
  2991. *------------- install function by vector number
  2992.  
  2993.                move.l   a2,-(sp)             ; save register
  2994.  
  2995.                move.l   a0,-(sp)             ; ^function
  2996.                move     d0,-(sp)             ; vector number
  2997.                move     #5,-(sp)             ; Setexc
  2998.  
  2999.                moveq.l  #-1,d1               ; ^function: don't change
  3000.                move.l   d1,-(sp)             ;  vector
  3001.                move     d0,-(sp)             ; vector number
  3002.                move     #5,-(sp)             ; Setexc
  3003.  
  3004.                trap     #13                  ; BIOS: get old vector
  3005.                addq     #8,sp                ; clean stack
  3006.  
  3007.                move.l   4(sp),a0             ; ^function
  3008.                move.l   d0,-4(a0)            ; save old vector
  3009.                trap     #13                  ; BIOS: install routine
  3010.                addq     #8,sp                ; clean stack
  3011.  
  3012.                move.l   (sp)+,a2             ; restore register
  3013.                rts                           ; bye
  3014.  
  3015.  
  3016. *------------- install function by vector address
  3017.  
  3018. .adr:          movem.l  a2-a4,-(sp)          ; save registers
  3019.  
  3020.                move.l   a0,a3                ; ^function
  3021.                move.l   d0,a4                ; ^vector
  3022.  
  3023.                clr.l    -(sp)                ; use usp as ssp
  3024.                move     #$20,-(sp)           ; Super
  3025.                trap     #1                   ; GEMDOS
  3026.                move.l   d0,2(sp)             ; save old sp
  3027.                move     #$20,(sp)            ; Super opcode for next call
  3028.  
  3029.                move.l   (a4),-4(a3)          ; save old vector content
  3030.                move.l   a3,(a4)              ; install function
  3031.  
  3032.                trap     #1                   ; GEMDOS (back to User mode)
  3033.                addq     #6,sp                ; clean stack
  3034.  
  3035.                movem.l  (sp)+,a2-a4          ; restore registers
  3036.                rts                           ; bye
  3037.  
  3038.  
  3039.  
  3040. *START
  3041. ****************************************************************************
  3042. *
  3043. *  nkc_vunlink: unlink function from XBRA vector list
  3044. *  # G U
  3045. *
  3046. *  nkc_vunlink() removes a function which was installed using the XBRA method.
  3047. *  For details see nkc_link(). If the XBRA list was corrupted, the function
  3048. *  aborts with an error code. This happens, when a non-XBRA routine is
  3049. *  installed on the same vector after the nkc_vlink() call of the function
  3050. *  to remove.
  3051. *
  3052. *  Note: the function automatically switches (temporary) to Supervisor mode
  3053. *        to prevent bus errors
  3054. *
  3055. *  In:   D0.L           vector descriptor
  3056. *        D1.W           mode:
  3057. *                       NKXM_NUM = D0.L contains a vector number
  3058. *                       NKXM_ADR = D0.L contains a vector address
  3059. *        A0.L           ^function to remove (NOT ^XBRA header!)
  3060. *
  3061. *  Out:  D0.W           status:
  3062. *                       0 = OK
  3063. *                       -1 = can't remove (XBRA list corrupted)
  3064. *        CCR            set according content of D0.W
  3065. *
  3066. *  Reg:  D:01234567   A:01234567   CCR
  3067. *          U**.....     **......   =D0.W
  3068. *
  3069. ****************************************************************************
  3070. *END
  3071.  
  3072. nkc_vunlink:   movem.l  d6-d7/a2/a6,-(sp)    ; save registers
  3073.  
  3074.                move.l   d0,d7                ; save vector descriptor
  3075.                move.l   a0,a6                ; save function address
  3076.                move     d1,d6                ; save mode
  3077.                bne.s    .adr                 ; address mode ->
  3078.  
  3079.  
  3080. *------------- check vector content by number
  3081.  
  3082.                moveq.l  #-1,d0               ; get current vector
  3083.                move.l   d0,-(sp)
  3084.                move     d7,-(sp)             ; vector number
  3085.                move     #5,-(sp)             ; Setexc
  3086.                trap     #13                  ; BIOS
  3087.                addq     #8,sp                ; clean stack
  3088.  
  3089.                cmp.l    d0,a6                ; function still on top?
  3090.                bne.s    .search              ; no ->
  3091.  
  3092. .restore:      move.l   -4(a6),-(sp)         ; restore old vector
  3093.                move     d7,-(sp)             ; vector number
  3094.                move     #5,-(sp)             ; Setexc
  3095.                trap     #13                  ; BIOS
  3096.                addq     #8,sp                ; clean stack
  3097.                bra.s    .okstat              ; exit
  3098.  
  3099.  
  3100. *------------- check vector content by address
  3101.  
  3102. .adr:          clr.l    -(sp)                ; use usp as ssp
  3103.                move     #$20,-(sp)           ; Super
  3104.                trap     #1                   ; GEMDOS
  3105.                move.l   d0,2(sp)             ; save old sp
  3106.                move     #$20,(sp)            ; Super opcode for next call
  3107.  
  3108.                move.l   d7,a0                ; vector address
  3109.                move.l   (a0),d0              ; vector content
  3110.                cmp.l    d0,a6                ; function still on top?
  3111.                bne.s    .search              ; no ->
  3112.  
  3113.                move.l   -4(a6),(a0)          ; yes: remove it
  3114.                bra.s    .okstat              ; exit
  3115.  
  3116.  
  3117. *------------- somebody installed a handler (hope he used XBRA ...)
  3118.  
  3119. .search:       move.l   d0,a0                ; ^current handler
  3120.                move.l   #'XBRA',d0           ; XBRA ID
  3121.  
  3122. .find_hnd:     cmp.l    -12(a0),d0           ; XBRA ID before routine?
  3123.                bne.s    .error               ; no!!! can't remove function!!
  3124.  
  3125.                move.l   -4(a0),a1            ; ^next entry in XBRA list
  3126.                cmp.l    a1,a6                ; next entry in list our function?
  3127.                beq.s    .found               ; yes ->
  3128.  
  3129.                move.l   a1,a0                ; no
  3130.                bra.s    .find_hnd            ; continue search
  3131.  
  3132. .found:        move.l   -4(a6),-4(a0)        ; yes: remove function
  3133.  
  3134. .okstat:       moveq.l  #0,d7                ; no error
  3135.                bra.s    .exit
  3136.  
  3137. .error:        moveq.l  #-1,d7               ; error! can't unlink function!
  3138.  
  3139. .exit:         tst      d6                   ; address mode?
  3140.                beq.s    .exit2               ; no ->
  3141.  
  3142.                trap     #1                   ; yes: switch to user mode first
  3143.                addq     #6,sp                ; with a GEMDOS Super() call
  3144.  
  3145. .exit2:        move     d7,d0                ; status code
  3146.                movem.l  (sp)+,d6-d7/a2/a6    ; restore registers
  3147.                rts                           ; bye
  3148.  
  3149.  
  3150.  
  3151.  
  3152. *START
  3153. ****************************************************************************
  3154. *
  3155. *  nkc_toupper: convert character to upper case
  3156. *  # G
  3157. *
  3158. *  A character is converted to upper case. Examples:
  3159. *
  3160. *  'a'   ->   'A'          (converted)
  3161. *  '/'   ->   '/'          (unchanged; there's no upper case version for this)
  3162. *  'A'   ->   'A'          (unchanged; already converted)
  3163. *
  3164. *
  3165. *  In:   D0.B           any character
  3166. *
  3167. *  Out:  D0.B           character converted to upper case
  3168. *
  3169. *  Reg:  D:01234567   A:01234567   CCR
  3170. *          U**.....     **......    *
  3171. *
  3172. ****************************************************************************
  3173. *END
  3174.  
  3175. nkc_toupper:   lea      toupper,a0           ; ^upper case translation table
  3176.                and      #$ff,d0              ; high byte = 0 for word operation
  3177.                move.b   (a0,d0),d0           ; convert
  3178.                rts                           ; bye
  3179.  
  3180.  
  3181.  
  3182. *START
  3183. ****************************************************************************
  3184. *
  3185. *  nkc_tolower: convert character to lower case
  3186. *  # G
  3187. *
  3188. *  The counterpart of nkc_toupper(). A character is converted to lower case.
  3189. *
  3190. *  In:   D0.B           any character
  3191. *
  3192. *  Out:  D0.B           character converted to lower case
  3193. *
  3194. *  Reg:  D:01234567   A:01234567   CCR
  3195. *          U**.....     **......    *
  3196. *
  3197. ****************************************************************************
  3198. *END
  3199.  
  3200. nkc_tolower:   lea      tolower,a0           ; ^lower case translation table
  3201.                and      #$ff,d0              ; high byte = 0 for word operation
  3202.                move.b   (a0,d0),d0           ; convert
  3203.                rts                           ; bye
  3204.  
  3205.  
  3206.  
  3207. ****************************************************************************
  3208. *                            LOCAL DATA SECTION                            *
  3209. ****************************************************************************
  3210.  
  3211.                .data
  3212.  
  3213. *  exception scan code table for cursor block keys
  3214. *
  3215. *  first entry.B:  NKCC key code
  3216. *  second entry.B: scan code returned by TOS
  3217. *
  3218. *  the table is terminated with both entries -1
  3219.  
  3220. xscantab:      .dc.b    NK_UP       ,  $48   ; cursor up
  3221.                .dc.b    NK_DOWN     ,  $50   ; cursor down
  3222.                .dc.b    NK_LEFT     ,  $4b   ; cursor left
  3223.                .dc.b    NK_LEFT     ,  $73   ; Control cursor left
  3224.                .dc.b    NK_RIGHT    ,  $4d   ; cursor right
  3225.                .dc.b    NK_RIGHT    ,  $74   ; Control cursor right
  3226.                .dc.b    NK_INS      ,  $52   ; Insert
  3227.                .dc.b    NK_CLRHOME  ,  $47   ; ClrHome
  3228.                .dc.b    NK_CLRHOME  ,  $77   ; Control ClrHome
  3229.                .dc.b    NK_HELP     ,  $62   ; Help
  3230.                .dc.b    NK_UNDO     ,  $61   ; Undo
  3231.                .dc.w    -1
  3232.  
  3233.  
  3234.  
  3235. *  deadkey table
  3236. *
  3237. *  first entry.B:  deadkey option mask (NKSf_D_...), 16 bits shifted down
  3238. *  second entry.W: ASCII code of deadkey
  3239. *  third entry.L:  ^deadkey match table
  3240. *
  3241. *  the table is terminated with an option mask of 0
  3242.  
  3243. deadtab:       .dc.w    NKSf_D_CIRCUM >> 16
  3244.                .dc.w    '^'
  3245.                .dc.l    d_circum
  3246.  
  3247.                .dc.w    NKSf_D_TILDE >> 16
  3248.                .dc.w    '~'
  3249.                .dc.l    d_tilde
  3250.  
  3251.                .dc.w    NKSf_D_AGUI >> 16
  3252.                .dc.w    '\''
  3253.                .dc.l    d_agui
  3254.  
  3255.                .dc.w    NKSf_D_GRAVE >> 16
  3256.                .dc.w    '`'
  3257.                .dc.l    d_grave
  3258.  
  3259.                .dc.w    NKSf_D_UMLAUT >> 16
  3260.                .dc.w    '¨'
  3261.                .dc.l    d_umlaut
  3262.  
  3263.                .dc.w    NKSf_D_QUOTE >> 16
  3264.                .dc.w    '\"'
  3265.                .dc.l    d_umlaut
  3266.  
  3267.                .dc.w    NKSf_D_SMOERE >> 16
  3268.                .dc.w    '°'
  3269.                .dc.l    d_smoere
  3270.  
  3271.                .dc.w    NKSf_D_CEDIL >> 16
  3272.                .dc.w    ','
  3273.                .dc.l    d_cedil
  3274.  
  3275.                .dc.w    NKSf_D_SLASH >> 16
  3276.                .dc.w    '/'
  3277.                .dc.l    d_slash
  3278.  
  3279.                .dc.w    0
  3280.  
  3281.  
  3282.  
  3283. *  deadkey match tables
  3284. *
  3285. *  first entry.B:  ASCII code generated by pressing deadkey and key code
  3286. *  second entry.B: key code (of the key which must be pressed directly after
  3287. *                  the deadkey)
  3288. *
  3289. *  the tables are terminated with both entries 0
  3290.  
  3291. d_circum:      .dc.b    '^','^'
  3292.                .dc.b    'â','a'
  3293.                .dc.b    'ê','e'
  3294.                .dc.b    'î','i'
  3295.                .dc.b    'ô','o'
  3296.                .dc.b    'û','u'
  3297.                .dc.w    0
  3298.  
  3299. d_tilde:       .dc.b    '~','~'
  3300.                .dc.b    'ñ','n'
  3301.                .dc.b    'Ñ','N'
  3302.                .dc.b    'ã','a'
  3303.                .dc.b    'õ','o'
  3304.                .dc.b    'Ã','A'
  3305.                .dc.b    'Õ','O'
  3306.                .dc.w    0
  3307.  
  3308. d_agui:        .dc.b    $27,$27              ; ' characters
  3309.                .dc.b    'é','e'
  3310.                .dc.b    'É','E'
  3311.                .dc.b    'á','a'
  3312.                .dc.b    'í','i'
  3313.                .dc.b    'ó','o'
  3314.                .dc.b    'ú','u'
  3315.                .dc.w    0
  3316.  
  3317. d_grave:       .dc.b    '`','`'
  3318.                .dc.b    'à','a'
  3319.                .dc.b    'è','e'
  3320.                .dc.b    'ì','i'
  3321.                .dc.b    'ò','o'
  3322.                .dc.b    'ù','u'
  3323.                .dc.b    'À','A'
  3324.                .dc.w    0
  3325.  
  3326. d_umlaut:      .dc.b    '¨','¨'
  3327.                .dc.b    $22,$22              ; " characters
  3328.                .dc.b    'ä','a'
  3329.                .dc.b    'ë','e'
  3330.                .dc.b    'ï','i'
  3331.                .dc.b    'ö','o'
  3332.                .dc.b    'ü','u'
  3333.                .dc.b    'ÿ','y'
  3334.                .dc.b    'Ä','A'
  3335.                .dc.b    'Ö','O'
  3336.                .dc.b    'Ü','U'
  3337.                .dc.w    0
  3338.  
  3339. d_smoere:      .dc.b    '°','°'
  3340.                .dc.b    'å','a'
  3341.                .dc.b    'Å','A'
  3342.                .dc.w    0
  3343.  
  3344. d_cedil:       .dc.b    ',',','
  3345.                .dc.b    'ç','c'
  3346.                .dc.b    'Ç','C'
  3347.                .dc.w    0
  3348.  
  3349. d_slash:       .dc.b    '/','/'
  3350.                .dc.b    'ø','o'
  3351.                .dc.b    'Ø','O'
  3352.                .dc.b    '½','2'
  3353.                .dc.b    '¼','4'
  3354.                .dc.w    0
  3355.  
  3356.  
  3357.  
  3358.                .if      NKCGEM=1
  3359.  
  3360. *  AES parameter block
  3361.  
  3362. aespb:          .dc.l   nkc_contrl
  3363.                 .dc.l   0                    ; set by nkc_init()
  3364.                 .dc.l   nkc_intin
  3365.                 .dc.l   nkc_intout
  3366.                 .dc.l   nkc_adrin
  3367.                 .dc.l   nkc_adrout
  3368.  
  3369. *  VDI parameter block
  3370.  
  3371. vdipb:          .dc.l   nkc_contrl
  3372.                 .dc.l   nkc_intin
  3373.                 .dc.l   nkc_ptsin
  3374.                 .dc.l   nkc_intout
  3375.                 .dc.l   nkc_ptsout
  3376.  
  3377.  
  3378. *  double click time table (values given in 1/200 s)
  3379.  
  3380. timetab:        .dc.l   85                   ; 0.425 s
  3381.                 .dc.l   63                   ; 0.315 s
  3382.                 .dc.l   49                   ; 0.245 s
  3383.                 .dc.l   42                   ; 0.210 s
  3384.                 .dc.l   30                   ; 0.150 s
  3385.  
  3386.                .endif   ;  .if NKCGEM=1
  3387.  
  3388.  
  3389.  
  3390. *  lower case to upper case conversion table
  3391. *  (array of 256 unsigned bytes)
  3392.  
  3393. toupper:
  3394.                .dc.b    $00,$01,$02,$03,$04,$05,$06,$07
  3395.                .dc.b    $08,$09,$0a,$0b,$0c,$0d,$0e,$0f
  3396.                .dc.b    $10,$11,$12,$13,$14,$15,$16,$17
  3397.                .dc.b    $18,$19,$1a,$1b,$1c,$1d,$1e,$1f
  3398.                .dc.b    " !",$22,"#$%&",$27,"()*+,-./0123456789:;<=>?"
  3399.                .dc.b    "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[",$5c,"]^_"
  3400.                .dc.b    "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~"
  3401.                .dc.b    "ÇÜÉâÄÀÅÇêëèïîìÄÅÉÆÆôÖòûùÿÖÜ¢£¥ßƒ"
  3402.                .dc.b    "áíóúÑѪº¿⌐¬½¼¡«»ÃÕØØŒŒÀÃÕ¨´†¶©®™"
  3403.                .dc.b    "ijIJאבגדהוזחטיכלמנסעפצקרשתןךםףץ§∧∞"
  3404.                .dc.b    "αβΓπΣσµτΦΘΩδ∮ϕ∈∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²³¯"
  3405.  
  3406.  
  3407. *  upper case to lower case conversion table
  3408. *  (array of 256 unsigned bytes)
  3409.  
  3410. tolower:
  3411.                .dc.b    $00,$01,$02,$03,$04,$05,$06,$07
  3412.                .dc.b    $08,$09,$0a,$0b,$0c,$0d,$0e,$0f
  3413.                .dc.b    $10,$11,$12,$13,$14,$15,$16,$17
  3414.                .dc.b    $18,$19,$1a,$1b,$1c,$1d,$1e,$1f
  3415.                .dc.b    " !",$22,"#$%&",$27,"()*+,-./0123456789:;<=>?"
  3416.                .dc.b    "@abcdefghijklmnopqrstuvwxyz[",$5c,"]^_"
  3417.                .dc.b    "`abcdefghijklmnopqrstuvwxyz{|}~"
  3418.                .dc.b    "çüéâäàåçêëèïîìäåéææôöòûùÿöü¢£¥ßƒ"
  3419.                .dc.b    "áíóúññªº¿⌐¬½¼¡«»ãõøøœœàãõ¨´†¶©®™"
  3420.                .dc.b    "ijIJאבגדהוזחטיכלמנסעפצקרשתןךםףץ§∧∞"
  3421.                .dc.b    "αβΓπΣσµτΦΘΩδ∮ϕ∈∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²³¯"
  3422.  
  3423. * note for both tables:
  3424. *
  3425. * $22 = " character
  3426. * $27 = ' character
  3427. * $5c = \ character (used as escape by the MadMac assembler)
  3428.  
  3429.  
  3430. *  scan code translation table
  3431. *
  3432. *  first entry.W : shift flags (NKFf_CTRL/SHIFT/ALT/FUNC), 8 bits shifted down
  3433. *  second entry.B: real scan code (index into key table)
  3434. *  third entry.B : simulated scan code (set by OS when the flags specified
  3435. *                  above are set)
  3436. *
  3437. *  The table is terminated with all entries 0.
  3438.  
  3439. scan_trans:    .dc.w    NKFf_SHIFT>>8        ; Shift F1
  3440.                .dc.b    $3b,$54
  3441.                .dc.w    NKFf_SHIFT>>8        ; Shift F2
  3442.                .dc.b    $3c,$55
  3443.                .dc.w    NKFf_SHIFT>>8        ; Shift F3
  3444.                .dc.b    $3d,$56
  3445.                .dc.w    NKFf_SHIFT>>8        ; Shift F4
  3446.                .dc.b    $3e,$57
  3447.                .dc.w    NKFf_SHIFT>>8        ; Shift F5
  3448.                .dc.b    $3f,$58
  3449.                .dc.w    NKFf_SHIFT>>8        ; Shift F6
  3450.                .dc.b    $40,$59
  3451.                .dc.w    NKFf_SHIFT>>8        ; Shift F7
  3452.                .dc.b    $41,$5a
  3453.                .dc.w    NKFf_SHIFT>>8        ; Shift F8
  3454.                .dc.b    $42,$5b
  3455.                .dc.w    NKFf_SHIFT>>8        ; Shift F9
  3456.                .dc.b    $43,$5c
  3457.                .dc.w    NKFf_SHIFT>>8        ; Shift F10
  3458.                .dc.b    $44,$5d
  3459.                .dc.w    (NKFf_FUNC|NKFf_CTRL)>>8   ; Control cursor left
  3460.                .dc.b    $4b,$73
  3461.                .dc.w    (NKFf_FUNC|NKFf_CTRL)>>8   ; Control cursor right
  3462.                .dc.b    $4d,$74
  3463.                .dc.w    (NKFf_FUNC|NKFf_CTRL)>>8   ; Control ClrHome
  3464.                .dc.b    $47,$77
  3465.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #1
  3466.                .dc.b    $02,$78
  3467.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #2
  3468.                .dc.b    $03,$79
  3469.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #3
  3470.                .dc.b    $04,$7a
  3471.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #4
  3472.                .dc.b    $05,$7b
  3473.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #5
  3474.                .dc.b    $06,$7c
  3475.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #6
  3476.                .dc.b    $07,$7d
  3477.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #7
  3478.                .dc.b    $08,$7e
  3479.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #8
  3480.                .dc.b    $09,$7f
  3481.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #9
  3482.                .dc.b    $0a,$80
  3483.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #10
  3484.                .dc.b    $0b,$81
  3485.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #11
  3486.                .dc.b    $0c,$82
  3487.                .dc.w    (NKFf_FUNC|NKFf_ALT)>>8    ; Alternate top row #12
  3488.                .dc.b    $0d,$83
  3489.                .dc.l    0                    ; terminator
  3490.  
  3491.  
  3492. *  ASCII code translation table for Control key
  3493. *
  3494. *  first entry.B:  modified ASCII code returned by TOS
  3495. *  second entry.B: original ASCII code as stored in key table
  3496. *
  3497. *  The table is terminated with both entries 0
  3498.  
  3499. asc_trans:     .dc.b    0,'2'                ; Control '2' becomes ASCII 0
  3500.                .dc.b    $1e,'6'              ; Control '6' becomes ASCII $1e
  3501.                .dc.b    $1f,'-'              ; Control '-' becomes ASCII $1f
  3502.                .dc.b    $a,$d                ; Control Return/Enter: $d -> $a
  3503.                .dc.w    0                    ; terminator
  3504.  
  3505.  
  3506. *  normalized key code -> scan code translation table
  3507. *  for unshifted key codes
  3508. *  indexed by function code (NK_...)
  3509.  
  3510. n_to_scan_u:   .dc.b    $00                  ; invalid key code
  3511.                .dc.b    $48                  ; cursor up
  3512.                .dc.b    $50                  ; cursor down
  3513.                .dc.b    $4d                  ; cursor right
  3514.                .dc.b    $4b                  ; cursor left
  3515.                .dc.b    $00                  ; reserved!
  3516.                .dc.b    $00                  ; reserved!
  3517.                .dc.b    $00                  ; reserved!
  3518.                .dc.b    $0e                  ; Backspace
  3519.                .dc.b    $0f                  ; Tab
  3520.                .dc.b    $72                  ; Enter
  3521.                .dc.b    $52                  ; Insert
  3522.                .dc.b    $47                  ; ClrHome
  3523.                .dc.b    $1c                  ; Return
  3524.                .dc.b    $62                  ; Help
  3525.                .dc.b    $61                  ; Undo
  3526.                .dc.b    $3b                  ; function key #1
  3527.                .dc.b    $3c                  ; function key #2
  3528.                .dc.b    $3d                  ; function key #3
  3529.                .dc.b    $3e                  ; function key #4
  3530.                .dc.b    $3f                  ; function key #5
  3531.                .dc.b    $40                  ; function key #6
  3532.                .dc.b    $41                  ; function key #7
  3533.                .dc.b    $42                  ; function key #8
  3534.                .dc.b    $43                  ; function key #9
  3535.                .dc.b    $44                  ; function key #10
  3536.                .dc.b    $00                  ; reserved!
  3537.                .dc.b    $01                  ; Esc
  3538.                .dc.b    $00                  ; reserved!
  3539.                .dc.b    $00                  ; reserved!
  3540.                .dc.b    $00                  ; reserved!
  3541.                .dc.b    $53                  ; Delete
  3542.  
  3543. *  normalized key code -> scan code translation table
  3544. *  for shifted key codes
  3545. *  indexed by function code (NK_...)
  3546.  
  3547. n_to_scan_s:   .dc.b    $00                  ; invalid key code
  3548.                .dc.b    $48                  ; cursor up
  3549.                .dc.b    $50                  ; cursor down
  3550.                .dc.b    $4d                  ; cursor right
  3551.                .dc.b    $4b                  ; cursor left
  3552.                .dc.b    $00                  ; reserved!
  3553.                .dc.b    $00                  ; reserved!
  3554.                .dc.b    $00                  ; reserved!
  3555.                .dc.b    $0e                  ; Backspace
  3556.                .dc.b    $0f                  ; Tab
  3557.                .dc.b    $72                  ; Enter
  3558.                .dc.b    $52                  ; Insert
  3559.                .dc.b    $47                  ; ClrHome
  3560.                .dc.b    $1c                  ; Return
  3561.                .dc.b    $62                  ; Help
  3562.                .dc.b    $61                  ; Undo
  3563.                .dc.b    $54                  ; function key #1
  3564.                .dc.b    $55                  ; function key #2
  3565.                .dc.b    $56                  ; function key #3
  3566.                .dc.b    $57                  ; function key #4
  3567.                .dc.b    $58                  ; function key #5
  3568.                .dc.b    $59                  ; function key #6
  3569.                .dc.b    $5a                  ; function key #7
  3570.                .dc.b    $5b                  ; function key #8
  3571.                .dc.b    $5c                  ; function key #9
  3572.                .dc.b    $5d                  ; function key #10
  3573.                .dc.b    $00                  ; reserved!
  3574.                .dc.b    $01                  ; Esc
  3575.                .dc.b    $00                  ; reserved!
  3576.                .dc.b    $00                  ; reserved!
  3577.                .dc.b    $00                  ; reserved!
  3578.                .dc.b    $53                  ; Delete
  3579.  
  3580.  
  3581.  
  3582. ****************************************************************************
  3583. *                             LOCAL BSS SECTION                            *
  3584. ****************************************************************************
  3585.  
  3586.                .bss
  3587.  
  3588.  
  3589. *              key code handler
  3590.  
  3591. pkey_unshift:  .ds.l    1                    ; ^unshifted key table
  3592. pkey_shift:    .ds.l    1                    ; ^shift key table
  3593. pkey_caps:     .ds.l    1                    ; ^CapsLock table
  3594. pshift:        .ds.l    1                    ; ^shift state system variable
  3595. sflags:        .ds.l    1                    ; special key flags
  3596. prvkey:        .ds.w    1                    ; previous key code
  3597. prvvalid:      .ds.b    1                    ; non-zero: prvkey is valid
  3598.                .even
  3599.  
  3600.  
  3601. *              button event handler
  3602.  
  3603.                .if      NKCGEM=1
  3604.  
  3605. bvar:           .ds.b   BI                   ; button event info block
  3606. tendtime:       .ds.l   1                    ; timer event end value
  3607. prvtime:        .ds.l   1                    ; previous timer event value
  3608. vdihnd:         .ds.w   1                    ; handle of VDI workstation
  3609. multibuf:       .ds.w   16+2                 ; buffer for evnt_multi parameters
  3610. buthnd:         .ds.b   1                    ; non-zero:button handler installed
  3611.                 .even
  3612.  
  3613.  
  3614.  
  3615. *              other stuff
  3616.  
  3617. kbdiorec:       .ds.l   1                    ; ^keyboard Iorec structure
  3618. iohead:         .ds.w   1                    ; NKCC's head pointer
  3619.  
  3620.                .endif   ; .if NKCGEM=1
  3621.  
  3622. sysclock:      .ds.l    1                    ; copy of 200 Hz system clock
  3623. timerflag:     .ds.b    1                    ; non-zero:200 Hz timer installed
  3624.                .even
  3625.  
  3626.  
  3627.  
  3628. *START
  3629. ****************************************************************************
  3630. *                            GLOBAL BSS SECTION                            *
  3631. ****************************************************************************
  3632. *END
  3633.  
  3634.                .bss
  3635.  
  3636. *START
  3637. *  GEM parameter arrays
  3638. *  (needed if using nkc_amulti())
  3639.  
  3640.                .if      NKCGEM=1
  3641.  
  3642. nkc_contrl:     .ds.w   32                   ; control array
  3643. nkc_intin:      .ds.w   32                   ; integer input array
  3644. nkc_intout:     .ds.w   32                   ; integer output array
  3645. nkc_adrin:      .ds.l   32                   ; address input array
  3646. nkc_adrout:     .ds.l   32                   ; address output array
  3647. nkc_ptsin:      .ds.l   32                   ; pointers input array
  3648. nkc_ptsout:     .ds.l   32                   ; pointers output array
  3649.  
  3650.                .endif   ; .if NKCGEM=1
  3651. *END
  3652.  
  3653. *START
  3654. * End Of File
  3655. *END
  3656.  
  3657.